ssh 命令引用有什么区别?
What difference does ssh command quoting make?
这些命令如何导致不同的输出?
⋊> ssh host bash -c 'cd /tmp; pwd'
/home/manu
⋊> ssh host "bash -c 'cd /tmp; pwd'"
/tmp
类似问题的回答 指出:
The trailing arguments are combined into a single string which is passed to as an argument to the -c option of your login shell on the remote machine.
在 *
的情况下,我可以理解这一点,但是在这个例子中,哪些部分将在本地进行评估?此外,bash 命令前的 --
也无济于事。
这里要理解的是 ssh
只是连接它的参数(与 $*
的方式相同),并将连接后的字符串传递给 sh -c
.
因此,在以下情况下:
ssh josh-play bash -c 'cd /tmp; pwd'
...ssh 运行s:
sh -c 'bash -c cd /tmp; pwd'
...因此,sh 运行s:
bash -c cd /tmp
pwd
...正如您可以自己测试的那样,bash -c cd /tmp
并没有做太多有用的事情(运行s 的脚本文本仅包含 cd
;/tmp
存储为参数,但脚本文本从不读取其参数,因此没有实际意义)。此外,一旦 bash
退出,我们就会回到父 sh
进程,其中 cd
从未 运行.
传递给外部 shell 的句法引号完全丢失,并且 pwd
不是由您手动触发的 bash
调用的(在这种用法中,只是在没有任何参数的情况下调用 cd
——/tmp
在 </code> 中,但是作为参数传递给 <code>cd
的脚本从不取消引用该变量)但是 sh
ssh 隐式调用。
如果您知道您的远程 sh
是由 bash 或 ksh 提供的——支持 $''
扩展的 shell——您可以执行以下操作任意 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"
上面的警告是,如果您的参数列表可以包含换行符或隐藏字符,bash 中的 printf %q
或 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"
这些命令如何导致不同的输出?
⋊> ssh host bash -c 'cd /tmp; pwd'
/home/manu
⋊> ssh host "bash -c 'cd /tmp; pwd'"
/tmp
类似问题的回答
The trailing arguments are combined into a single string which is passed to as an argument to the -c option of your login shell on the remote machine.
在 *
的情况下,我可以理解这一点,但是在这个例子中,哪些部分将在本地进行评估?此外,bash 命令前的 --
也无济于事。
这里要理解的是 ssh
只是连接它的参数(与 $*
的方式相同),并将连接后的字符串传递给 sh -c
.
因此,在以下情况下:
ssh josh-play bash -c 'cd /tmp; pwd'
...ssh 运行s:
sh -c 'bash -c cd /tmp; pwd'
...因此,sh 运行s:
bash -c cd /tmp
pwd
...正如您可以自己测试的那样,bash -c cd /tmp
并没有做太多有用的事情(运行s 的脚本文本仅包含 cd
;/tmp
存储为参数,但脚本文本从不读取其参数,因此没有实际意义)。此外,一旦 bash
退出,我们就会回到父 sh
进程,其中 cd
从未 运行.
传递给外部 shell 的句法引号完全丢失,并且 pwd
不是由您手动触发的 bash
调用的(在这种用法中,只是在没有任何参数的情况下调用 cd
——/tmp
在 </code> 中,但是作为参数传递给 <code>cd
的脚本从不取消引用该变量)但是 sh
ssh 隐式调用。
如果您知道您的远程 sh
是由 bash 或 ksh 提供的——支持 $''
扩展的 shell——您可以执行以下操作任意 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"
上面的警告是,如果您的参数列表可以包含换行符或隐藏字符,bash 中的 printf %q
或 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"