通过 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 hello
和 echo 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 ~ %
在调试远程运行各种命令的脚本时,我注意到从 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 hello
和 echo 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 ~ %