为什么bash -c "false; echo $?"会输出0?

3

我正在编写一个脚本,尝试在服务器上运行一些命令(通过SSH),并在屏幕上显示它们是否成功。

我注意到$?的奇怪行为,即当前一个命令失败时它不是0

最初,我的代码如下:

ssh <user>@<server> <<EOF
    false
    if [ $? -ne 0 ]; then
        echo "It failed"
    else
        echo "It worked"
    fi
EOF

我将脚本复制并粘贴到<<EOFEOF标签之间,会打印It failed。如果我使用ssh部分运行它,它会打印It worked。为了简化,我尝试了以下操作:

ssh <user>@<server> <<EOF
    false
    echo $?
EOF

发生了同样的事情。如果我复制粘贴或者输入这些命令,它会打印出1,但是如果我运行全部(包括 ssh),它会打印出0

如果我直接这样使用bash,也会出现相同的错误。

bash <<EOF
    false
    echo $?
EOF

或者

bash -c "false; echo $?"

为什么会发生这种情况?我该如何在此情境下检查上一个命令是否失败?

1
也许 command || echo "it failed" 或者 command && echo "it succeeded" 会有所帮助。 - Rambo Ramon
1个回答

9
这是由于变量扩展引起的。当你输入 bash -c "false; echo $?" 时,变量在命令运行之前被扩展。因此,如果之前的命令成功,那么你的命令就像 bash -c "false; echo 0;" 一样。
要得到正确的结果,请尝试使用 bash -c 'false; echo $?' 。这可以防止变量扩展,在解释时才会扩展。
对于here文档版本,请执行以下操作:
bash << 'EOF'
false
echo $?
'EOF'

在这种情况下,您需要引用此文档的分隔符。但请注意,您必须使用键入命令的 shell 的语法。在此示例中,我使用的是 tcsh,它要求使用完全相同的开放和关闭分隔符。在 bash 下,关闭分隔符必须是引号删除后的开放分隔符。

1
他如何使用EOF抑制原始的ssh设置中的早期扩展? - Rambo Ramon
2
我猜还是错了。你只需要引用第一个 EOF - Rambo Ramon
根据您用于启动命令的 shell(我尝试过 tcsh)而定。 - Jean-Baptiste Yunès
1
Rambo 在 bash 中是正确的,你只需要引用第一个 EOF。我修复了我的脚本! 谢谢你们两个的帮助! - Vlad V
不是,我使用tcsh输入命令,所以<<是here文档用于tcshtcsh读取这些行并将它们推送bash中。 - Jean-Baptiste Yunès
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接