TeN*_*NoX 1 linux ssh bash quotes quoting
这些命令如何导致不同的输出?
?> ssh host bash -c 'cd /tmp; pwd'
/home/manu
?> ssh host "bash -c 'cd /tmp; pwd'"
/tmp
Run Code Online (Sandbox Code Playgroud)
这里对类似问题的回答指出:
尾随参数组合成一个字符串,该字符串作为参数传递给远程计算机上登录shell的-c选项.
如果*我能理解这一点,但在这个例子中本地评估哪个部分?此外,--在bash命令之前没有帮助.
这里要理解的是ssh简单地连接它的参数(以相同的方式$*连接),并将该连接的字符串传递给sh -c.
因此,在以下情况下:
ssh josh-play bash -c 'cd /tmp; pwd'
Run Code Online (Sandbox Code Playgroud)
... ssh运行:
sh -c 'bash -c cd /tmp; pwd'
Run Code Online (Sandbox Code Playgroud)
...因此,sh运行:
bash -c cd /tmp
pwd
Run Code Online (Sandbox Code Playgroud)
...并且你可以测试自己,bash -c cd /tmp并没有做太多有用的事情(它运行的脚本文本只包含cd; /tmp作为参数存储,但脚本文本永远不会读取它的参数,这样做没有意义).而且,一旦bash退出,我们就会回到父sh进程中,而进程cd从未运行过.
传递给你的外壳句法引号完全丧失,而pwd被不被调用bash,你手动触发(在这种用法,只是调用cd不带任何参数- /tmp是$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 list
printf -v rmt_cmd '%q ' bash -c 'cd /tmp; pwd'
# pass that through to be run by the remote sh -c
ssh josh-play "$rmt_cmd"
Run Code Online (Sandbox Code Playgroud)
上面的警告是,如果您的参数列表可以包含换行符或隐藏字符,则printf %q在bash或ksh中可以以不保证POSIX sh能够读取的形式将其转义.为了避免这种情况
# ask your shell to generate an eval-safe quoted form of your argument list
printf -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"
Run Code Online (Sandbox Code Playgroud)