【问题标题】:What difference does ssh command quoting make?ssh 命令引用有什么区别?
【发布时间】:2017-07-21 02:32:07
【问题描述】:

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

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

对类似问题here 的回答指出:

尾随参数组合成一个字符串,作为参数传递给远程计算机上登录 shell 的 -c 选项。

如果是*,我可以理解这一点,但是在这个例子中,什么部分会在本地进行评估?此外,在 bash 命令之前的 -- 也无济于事。

【问题讨论】:

标签: linux bash ssh quotes quoting


【解决方案1】:

这里要理解的是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 退出,我们就会回到父进程sh,其中cd 从未运行过。

传递给你的外壳的语法引号完全丢失了,pwd 不是由你手动触发的bash 调用的(在这种用法中,它只是在没有任何参数的情况下调用cd -- @ 987654336@ 在$1 中,但作为参数传递给cd 的脚本从不取消引用该变量)而是通过ssh 隐式调用的sh


如果您知道您的远程 sh 是由 bash 或 ksh 提供的 - 一个支持 $'' 扩展的 shell - 您可以对任意 argv 数组执行以下操作(在本例中为 bash、@987654343 @,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"

上面的警告是,如果您的参数列表可以包含换行符或隐藏字符,则 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"

【讨论】:

    猜你喜欢
    • 2023-01-26
    • 2017-09-04
    • 2019-08-29
    • 2011-11-23
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多