我正在构建这个项目,我必须使用ssh执行UNIX命令。这是我的问题:当我在UNIX shell中执行以下命令时,
echo "Hello World"
它产生输出:
Hello World
中间有5个空格,因为参数在双引号内给出。我想用ssh实现相同的效果。我试图使用反斜杠转义双引号,如下所示:
ssh localhost echo \"Hello World\"
因为我不希望bash处理引号。但它只是产生
Hello World
" Hello"之后只有一个空格。 那是为什么?
答案 0 :(得分:2)
ssh
通过调用一个远程shell来执行一个命令,该远程shell的脚本由一组本地参数组成,这些参数与它们之间的空格连接在一起。
如果你跑:
# This has only syntactic quotes -- none of the quotes are literal.
ssh somehost echo "Hello World"
..然后传递给ssh
的参数列表(在C语法中,不包括主机名和ssh命令本身)是{ "echo", "Hello World", NULL }
。
连接成一个字符串,然后变为"echo Hello World"
。
因此,远程shell运行echo Hello World
,它没有语法引号。
如果你跑:
ssh somehost echo \"Hello World\"
...然后命令列表(再次,在C语法中)是{ "echo", "\"Hello", "World\"", NULL }
:引号是文字的,但是在分词期间本地shell(在运行SSH之前)删除了空格过程
连接成一个字符串,变为echo "Hello World"
。因此,你会得到报价,但会失去你的空间。
相比之下,作为一个有效(但不是特别是最佳实践)的例子,请考虑:
ssh somehost echo \"Hello" "World\"
在这里,你传递ssh
两个参数:开头和结尾的\"
是第一个shell的文字(没有句法意义,所以单词Hello
是没有引用的第一个shell);但是只是围绕空格的"
是语法的,并告诉shell在调用ssh
时保留该空格(因此引用了空格)。因此,您得到{ "echo", "\"Hello World\"", NULL }
,它与字符串echo "Hello World"
连接。
最佳做法是通过仅将一个字符串传递给包含您要运行的整个脚本的ssh来避免此行为。
# This works
ssh somehost 'echo "Hello World"'
...如果你想以编程方式生成该字符串,你可以这样做(如果你知道你的远程shell是bash - 甚至bash-in - /bin/sh
模式是安全的):
remote_command=( echo "Hello World" )
printf -v remote_command_q '%q ' "${remote_command[@]}"
ssh somehost "$remote_command_q"
要使用任何符合POSIX的远程shell安全地执行此操作,请参阅How to have simple and double quotes in a scripted ssh command中的Python辅助答案
答案 1 :(得分:1)
引号仅出现在客户端上,表示服务器看到:
echo Hello World
但是此时引号已经丢失,因此空格会崩溃。
您可以在整个命令周围使用单引号:
ssh localhost 'echo "Hello World"'
现在本地shell不处理字符串,因此内部引号保持不变。
带有转义引号的情况意味着引号在本地shell上无效,因此空格在本地折叠,然后服务器看到:
echo "Hello World"