通过 ssh 执行的命令没有返回正确的返回代码

通过 ssh 执行的命令没有返回正确的返回代码

这为什么不起作用?

$ ssh vm "bullshitcommand; echo $?"
bash: bullshitcommand: command not found
0

我期望非零返回码。

答案1

原因:

echo $?,你实际上是在发送一个局部变量$?并要求在 ssh shell 中回显它,看起来是这样。你可以在 ssh 语句前使用不存在的命令来证明这一点。例如:

notexistingcommand; ssh vm "echo $?"输出

bash:不存在的命令:未找到命令

127

甚至

export var=123; ssh vm "echo $var"输出

123

解决方案:

要使用远程变量,您可以执行转义,它将输出 -1(或 127):

ssh vm "nonexistentcmd; echo \$?"

或者您可以使用单引号 () 因为它们不扩展变量并且按字面意思理解 $ 符号

ssh vm 'nonexistentcmd; echo $?'

答案2

不要说:

ssh vm "bullshitcommand; echo $?"

说:

ssh vm "bullshitcommand"
echo $?

返回代码ssh将与远程命令的返回代码相同。

答案3

你说,这不起作用:

$ ssh vm "bullshitcommand; echo $?"
bash: bullshitcommand: command not found
0

首先我们来分析一下人物:

"not important $? not important"

在客户端本地解释,而不是在服务器上这将被解释为:

"not important 0 not important"

因为客户端(本地)特殊变量 $? 通常为 0。为了防止这种情况,您应该进行转义,因为您希望将文本 $? 按原样放置而不进行替换:

"not important \$? not important"

另一个问题是你做了什么。你只是丢失了你感兴趣的退出代码。让我们看下面的例子:

$ ssh vm "bullshitcommand; echo external ret: \$?"; echo internal ret: $?
bash: bullshitcommand: command not found
external ret: 127
internal ret: 0

发生了什么?外部 $? 截取退出代码,然后一步之后,您将获得 echo 命令的退出代码。这始终是 0,因为 echo 不可能崩溃 :) 最后 ssh 服务器从最后一个命令获取退出代码,它是从 echo 获得的,为 0。之后 ssh 客户端给出 0 代码。最后这导致 ssh 命令以 0 退出。

您可以通过临时保存 $? 值来解决此问题,例如:

$ ssh vm "bullshitcommand; exitcode=\$? echo external ret: \$exitcode; exit \$exitcode"; echo internal ret: $?
bash: bullshitcommand: command not found
external ret: 127
internal ret: 127

当你收到结果时,你就到家了 :)。问题是,exitstatus 是不持久的,上面有解决办法。记住退出 :)

但请注意历史上损坏的 ssh 服务器和客户端。有时服务器和/或客户端会忽略退出状态并永久返回 0 返回代码。如果必须确定,请测试它。如果遇到这种情况,您应该升级软件,或者通过 stdout 流传输退出代码来采取一些解决方法。对于编写它的脚本和程序员来说,这是额外的工作。

相关内容