ssh命令引用有什么区别?

这些命令如何导致不同的输出?

⋊> ssh host bash -c 'cd /tmp; pwd' /home/manu ⋊> ssh host "bash -c 'cd /tmp; pwd'" /tmp 

对此类似问题的回答是:

尾部参数组合成一个string,作为parameter passing给远程机器上loginshell的-c选项。

*情况下,我可以理解这一点,但在这个例子中,什么部分将在本地进行评估? 另外,在bash命令之前没有帮助。

Solutions Collecting From Web of "ssh命令引用有什么区别?"

这里要理解的是, ssh只是简单地连接它的参数(和$*一样),并把这个连接的字符串传递给sh -c


因此,在以下情况下:

 ssh josh-play bash -c 'cd /tmp; pwd' 

… ssh运行:

 sh -c 'bash -c cd /tmp; pwd' 

…因此,sh运行:

 bash -c cd /tmp pwd 

…你可以测试自己, bash -c cd /tmp没有太多有用的东西(它运行的脚本文本只包含cd ; /tmp作为参数存储,但是脚本文本从不读取它的参数,使这个模拟)。 而且,一旦bash退出,我们就回到父进程中,而cd从未运行过。

传递到外层shell的语法引号完全丢失了, pwd不是由你手动触发的bash调用的(在这个用法中,只是简单地调用cd而不带任何参数 – /tmp$1 ,但脚本通过作为cd的参数,不要解除引用该变量),而是通过ssh隐式调用的sh


如果你知道你的远程sh是由bash或ksh提供的 – 一个支持$''扩展名的shell,你可以为任意的argv数组(在这种情况下为bash-ccd /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" 

需要注意的是,如果您的参数列表可以包含换行符或隐藏字符,则bash或ksh中的printf %q可以以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"