2017-03-01 64 views
1

这些命令如何导致不同的输出?ssh命令引用有什么不同?

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

到类似的问题here的回答说:

尾随参数组合成被传递到作为参数传递给你的登录shell对-c选项一个字符串远程机器。

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

+0

看到这个职位:奇怪的“上海-c”行为时,通过SSH运行(http://unix.stackexchange.com/questions/340221/strange-sh-c-behavior- when-run-through-ssh) – codeforester

+1

@codeforester,...尽管我认为这应该超出'sh -c',因为这肯定是一个在其他场景中相关的问题。 –

回答

6

这里要理解的是,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并没有太多的用处ul(它运行的脚本文本仅包含cd; /tmp作为参数存储,但脚本文本从不读取其参数,因此没有意义)。此外,只要bash退出,我们又回到了父项sh过程中,其中cd从未运行过。

传递给你的外壳句法引号完全丧失,而pwd是由您手动触发(在这种用法,只是调用cd不带任何参数的bash不会调用 - /tmp$1,但该脚本作为参数传递给cd从不解除引用该变量),而是通过ssh隐式调用的sh


如果你知道你的远程sh由bash或ksh的提供 - 外壳支持$''分机 - 你可以做任意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" 

需要说明上述的是,如果您的参数列表可以包含换行符或隐藏字符,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"