我发现当我在本地运行脚本时,比如说:
那么我应该如何实现这个呢?
./run.sh a "b c"
当在run.sh中使用"$@"时,它将识别两个参数。但是,当通过ssh在远程机器上使用时,情况就不同了。
ssh user@host ./run.sh a "b c"
那么我应该如何实现这个呢?
ssh user@host ./run.sh a "b c"
发生的情况是,本地 shell 将该命令解析为“单词”(应用并删除任何引号和/或反斜杠),并得到“ssh
”、“user@host
”、“./run/sh
”、“a
”和“b c
”。它将第一个(ssh
)作为命令,并将其余部分作为参数传递给它。ssh 将“user@host
”作为 ssh 的目标地址,并且(这是关键的一点)只是将其余部分拼接在一起(用空格隔开)作为要运行的远程命令。这会将“./run.sh a b c
”作为远程命令。然后将其传递给远程 shell,后者(因为引号现在已经消失)将“a
”、“b
”和“c
”解释为单独的参数。ssh user@host './run.sh a "b c"'
本地 shell 应用并删除单引号,因此双引号由远程 shell 应用。请注意,引号通常不会嵌套在自身/彼此之内,但由于双引号在单引号字符串中没有特殊含义,所以在这种情况下可以正常工作。您也可以对两个级别使用双引号,但需要转义内部引号:
ssh user@host "./run.sh a \"b c\""
实际上,这里的外部双引号并没有起到任何作用(它们使整个内容成为ssh的一个参数,但如果它们是多个参数,它们仍然会被粘在一起,所以...)。你实际上可以删除它们:
ssh user@host ./run.sh a \"b c\"
实际上有很多方法可以做到这一点,结合本地和远程shell上的各种引用/转义选项:
ssh user@host ./run.sh a '"b c"'
ssh user@host "./run.sh a 'b c'"
ssh user@host './run.sh a b\ c'
ssh user@host ./run.sh a b\\ c
顺便说一下,通常echo
输出某些内容并不是发现你的参数被如何解析的好方法,因为它只是将其参数使用空格连接起来。但由于在创建远程命令时ssh
执行的也是相同的操作,您可以将ssh user@host
替换为echo
,以查看实际传递给远程shell的内容:
$ echo ./run.sh a "b c"
./run.sh a b c
$ echo './run.sh a "b c"'
./run.sh a "b c"
$ echo "./run.sh a \"b c\""
./run.sh a "b c"
$ echo "./run.sh a 'b c'"
./run.sh a 'b c'
$ echo ./run.sh a b\\ c
./run.sh a b\ c
ssh user@host 'bash -c "./run.sh a \"b c\""'
我遇到了与其他人指出的类似问题,使用双引号而不是单引号帮助我解决了这个问题。
ssh ubunut@12.3232.34.232 "ls -a"
ssh user@host './run.sh a "b c"'
,它是否有效? - melpomene