当通过ssh传递时,为什么带引号的空格命令不起作用? [英] Why doesn't a command with quoted whitespace work when passed over ssh?
问题描述
我正在构建此项目,在该项目中必须使用ssh执行UNIX命令。这是我的问题:在UNIX shell中执行以下命令时,
I am building this project in which I have to execute UNIX commands using ssh. Here is my question : When I execute the following command in a UNIX shell,
echo "Hello World"
它产生输出:
Hello World
参数之间有5个空格用双引号引起来。我也想通过ssh达到相同的效果。我试图使用反斜杠转义双引号,如下所示:
With 5 spaces in between as the arguments were given within double quotes. I want to achieve the same effects with ssh as well. I am trying to escape the double quotes using backslash as follows :
ssh localhost echo \"Hello World\"
因为我不希望bash处理报价。但这只会产生
as I do not want bash to process the quotes. But it just produces
Hello World
Hello之后只有一个空格
为什么?
There is only one space after "Hello" Why is that?
推荐答案
ssh
执行一个命令,该命令是通过调用远程shell给出的,该脚本由脚本组成,该脚本由完整的本地参数集以及它们之间的空格组成。
ssh
executes a command it's given by invoking a remote shell with a script composed of the full set of local arguments concatenated together with whitespace between them.
如果您运行:
# This has only syntactic quotes -- none of the quotes are literal.
ssh somehost echo "Hello World"
..然后将此参数列表传递给 ssh
(使用C语法,不包括主机名和ssh命令本身)为 { echo, Hello World,NULL}
。
..then this list of arguments passed to ssh
(in C syntax, excluding the hostname and the ssh command itself) is { "echo", "Hello World", NULL }
.
连接成一个字符串,然后变成 echo Hello World
。
Concatenated together into a string, this then becomes "echo Hello World"
.
因此,远程shell运行 echo Hello World
,它没有语法引号。
Thus, the remote shell runs echo Hello World
, which has no syntactic quotes.
如果您运行:
ssh somehost echo \"Hello World\"
...然后是命令列表(再次使用C语法)是 { echo, \ Hello, World\,NULL}
:引号是文字,但空格已由本地外壳程序删除(在运行SSH之前)在分词过程中。
...then the list of commands (again, in C syntax) is { "echo", "\"Hello", "World\"", NULL }
: The quotes are literal, but the spaces were removed by the local shell (before SSH was run) during the word-splitting process.
连接到字符串中后,它会成为 echo Hello World
。因此,您得到的是报价,但是却失去了空格。
Concatenated into a string, this becomes echo "Hello World"
. Thus, you get quotes, but lose your spaces.
相反,这是可行的(但不是最佳实践) )示例,请考虑:
By contrast, as a working (but not particularly best-practice) example, consider:
ssh somehost echo \"Hello" "World\"
在这里,您要传递 ssh
两个参数: \
的开头和结尾是第一个shell的文字(没有语法含义,因此 Hello
是第一个shell未引用);但是仅在空白周围的
是语法上的,并告诉Shell保留该空白(因此引用了 space )调用 ssh
时。因此,您将得到 { echo, \ Hello World\,NULL}
,它连接到字符串 echo Hello世界。
Here, you're passing ssh
two arguments: The \"
s at the beginning and end are literal to the first shell (having no syntactical meaning, so the word Hello
is to that first shell unquoted); but the "
s just surrounding the whitespace is syntactical, and tells the shell to preserve that whitespace (so the spaces are quoted) when invoking ssh
. Thus, you get { "echo", "\"Hello World\"", NULL }
, which concatenates to the string echo "Hello World"
.
最佳做法是通过仅传递单个字符串来避免此行为
The best practice is to avoid this behavior by passing only a single string to ssh containing the entire script you want to run.
# This works
ssh somehost 'echo "Hello World"'
...如果要以编程方式生成该字符串,则可以这样操作(如果您知道您的远程shell是bash -即使bash-in- / bin / sh
模式也是安全的):
...if you want to generate that string programatically, you can do so as such (if you know that your remote shell is bash -- even bash-in-/bin/sh
mode is safe):
remote_command=( echo "Hello World" )
printf -v remote_command_q '%q ' "${remote_command[@]}"
ssh somehost "$remote_command_q"
要使用任何符合POSIX的远程shell安全地执行此操作,请参见< a href = https://stackoverflow.com/questions/45308395/how-to-have-simple-and-double-quotes-in-a-scripted-ssh-command>如何在脚本化的ssh命令中使用单引号和双引号
To do that safely with any POSIX-compliant remote shell, see the Python-assisted answer in How to have simple and double quotes in a scripted ssh command
这篇关于当通过ssh传递时,为什么带引号的空格命令不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!