通过 SSH 使用 bash -c 时缺少第一个回显

First echo missing when using bash -c over SSH

在调试远程运行各种命令的脚本时,我注意到从 echo 获取输出时出现一些问题。

我意识到 bash -c 在这里不是必需的,但它仍然让我想知道。

在我的 shell:

> bash -c "echo hello && echo hi"
hello
hi

但是,如果我将 SSH 引入图片中:

> ssh ${myhost} bash -c "echo hello && echo hi"

hi

然而,date 输出,即使第一个 echo 没有:

> ssh ${myhost} bash -c "date && echo hi"
Thu Jun  3 21:15:26 UTC 2021
hi

这是怎么回事?

到达服务器的命令是:bash -c echo hello && echo hi

即不带引号

如果你在本地 运行 这个 cde,它会产生相同的输出

如果你想要好的结果

ssh mm 'bash -c "echo hello && echo hi"'

当你像这样通过 ssh 运行 命令时,它会被解析两次:首先在本地计算机上(在它作为参数传递给 ssh 命令之前),然后再次在实际执行之前在远程计算机上。每次解析时,shell 将应用 并删除 引号和转义符。这意味着在将命令发送到远程 shell 之前,本地 shell 会应用和删除命令周围的双引号。那么这个命令看起来像什么:

bash -c "echo hello && echo hi"

在远程 shell 看到它时变成这样:

bash -c echo hello && echo hi

...这是两个独立的命令,bash -c echo helloecho hi。第二个 echo hi 可以正常工作,但第一个可能不会。

对于bash -c,紧随其后的参数被视为要执行的命令字符串,任何进一步的参数都分配给[=19=]</code>等,因为它运行秒。所以 <code>bash -c echo hello 只需 运行s echo 并将 [=19=] 设置为“hello”。所以它打印一个空行。

如果你想让命令按照你的预期执行,你需要两层引号and/or转义,一层被本地shell应用和移除,另一层被应用和移除被遥控器移除 shell。这些中的任何一个都可以工作:

# Single-quotes for local shell, double for remote
ssh ${myhost} 'bash -c "echo hello && echo hi"'

# Double-quotes for local shell, single for remote
ssh ${myhost} "bash -c 'echo hello && echo hi'"

 # Double-quotes for local shell, escaped doubles for remote
ssh ${myhost} "bash -c \"echo hello && echo hi\""

# Single-quotes for local shell, escaped characters for remote
ssh ${myhost} 'bash -c echo\ hello\ \&\&\ echo\ hi'

...还有更多的可能性。请注意,如果命令字符串包含变量引用或命令替换之类的内容,您需要注意是否希望它们在本地或远程计算机上扩展,并确保您使用的 quoting/escaping 方法可以实现这一点。

顺便说一句,在这种情况下,由于您 运行 使用 bash -c 命令,实际上 third 解析层由 shell 由 bash -c 调用。如果该命令有任何需要 quoting/escaping,保持水平直线将更加复杂。

也可以尝试使用“;”作为分隔符

ssh ${myserver} "echo hello; echo hi"

testuser@mymac ~ % ssh ${myserver} "echo hello; echo hi"
hello
hi
testuser@mymac ~ %