You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确编写用于SSH远程执行命令的Shell函数?

如何正确编写用于SSH远程执行命令的Shell函数?

我明白你想做的事——写一个通用函数,把它当前缀用,后面跟的命令就能直接在远程服务器上执行对吧?先说说你原来写法的问题:你用< ${cmdArgs[@]}是想把命令内容传给远程的bash -s,但这个语法是重定向文件用的,不是传递参数内容,所以才会报“ambiguous redirect”错误。

你后来改的写法虽然能跑,但用$*有隐患——$*会把所有参数拼成一个字符串,要是参数里有空格、引号或者特殊字符,远程shell解析的时候很容易出错。比如如果${webserverUser}是带空格的名字(比如"web admin"),$*会把它拆成两个参数,远程的sudo会把admin当成额外参数,直接报错。

给你几个更靠谱的写法,按场景选:

最简单直接的写法

如果远程服务器的默认shell是bash(或者你不需要特殊的bash特性),直接把参数原封不动传给ssh就行,这是最稳妥的方式:

function NC_SSH_CMD () {
    ssh root@myserver.intern "$@"
}

用"$@"的好处是,它会保留每个参数的边界——你调用函数时传的每个空格、引号、特殊字符,都会原原本本传递到远程服务器。比如你原来的调用:

NC_SSH_CMD sudo -u "${webserverUser}" php ${nextcloudFileDir}/occ maintenance:mode --on

每个参数(包括带变量的部分)都会被正确解析,完全不会乱。

需要用bash -s的场景

如果你必须用bash -s(比如远程默认shell不是bash,或者需要用到bash的特定语法),可以这么写:

function NC_SSH_CMD () {
    ssh root@myserver.intern bash -s -- "$@"
}

这里的--是告诉bash:“后面的都是命令参数,别把它们当成我的选项”,避免命令里有-开头的参数被bash误判。同样用"$@"保证参数的完整性。

另一种标准输入传递的写法

如果你的命令需要从标准输入读取内容,也可以用管道把参数传过去,但要注意用null字符分隔避免空格问题:

function NC_SSH_CMD () {
    printf '%s\0' "$@" | ssh root@myserver.intern bash -s --
}

不过这种场景比较少见,一般前面两种写法就够了。

总结一下:优先用ssh ... "$@"的写法,既简单又能避免绝大多数参数解析问题,比你用$*的写法可靠多了。

备注:内容来源于stack exchange,提问作者Bud Spencer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 15:34:33