这里要理解的是,
ssh只需将其参数串联起来(以相同的方式
$*),然后将串联的字符串传递给
sh -c。
因此,在以下情况下:
ssh josh-play bash -c 'cd /tmp; pwd'
… ssh运行:
sh -c 'bash -c cd /tmp; pwd'
…因此,sh运行:
bash -c cd /tmppwd
…并且您可以测试自己,
bash -c cd /tmp没有做太多有用的事情(它运行的脚本文本仅由
cd;
组成
/tmp作为参数存储,但是脚本文本从不读取其参数,因此无济于事)。而且,一旦
bash退出,我们就返回到父
sh进程,该进程
cd从未运行过。
传递给外壳程序的句法引号完全丢失,并且
pwd不是由
bash您手动触发的调用(在此用法中,该调用只是在
cd没有任何参数的情况下调用了
/tmpin)
$1,而是作为参数传递给
cd从不取消引用的脚本该变量),但由
shssh隐式调用。
如果你知道你的遥控器
sh是由bash或ksh的提供-壳配套的
$''延伸-你可以做任意argv数组以下(在这种情况下
bash,
-c,
cd/tmp; pwd):
# ask your shell to generate an eval-safe quoted form of your argument listprintf -v rmt_cmd '%q ' bash -c 'cd /tmp; pwd'# pass that through to be run by the remote sh -cssh josh-play "$rmt_cmd"
上面的警告是,如果您的参数列表可以包含换行符或隐藏的字符,则
printf %qbash或ksh可以以不能保证POSIX
sh能够读取的形式对其进行转义。为了避免这种情况:
# ask your shell to generate an eval-safe quoted form of your argument listprintf -v rmt_cmd '%q ' bash -c 'cd /tmp; pwd'# ...and use bash to evaluate that quoted form.ssh josh-play 'exec bash -s' <<<"$rmt_cmd"



