我有一些简单的冒烟测试脚本,通常如下所示:
set -e
run-command
run-other-command
echo ok
当我期望命令成功时,这非常有效;如果失败,set -e
将提前退出脚本并使用非零退出代码。
然而,有时我预计命令会失败,并且我希望脚本以其他方式退出(即,如果命令以代码 0 退出)。我本以为我可以写:
set -e
run-command-that-succeeds
! run-command-that-fails
但这会忽略退出代码。 bash 手册页是这样描述的set -e
:
如果命令的返回值与 ! 取反,则 shell 不会退出 [...]
有效的替代方案是:
set -e
! run-command-that-fails
[[ $? -eq 0 ]]
和
set -e
if run-command-that-fails; then
exit 1
fi
这些是最好的选择,还是有更惯用的替代方法可以在命令成功时退出?
答案1
我的测试表明这(! run-command-that-fails)
是一个解决方案。它run-command-that-fails
在子 shell 中运行。
run-command-that-fails
如果您出于某种原因需要在主 shell 中运行,那么您需要另一个解决方案。我注意到那{ ! run-command-that-fails; }
是不是一个办法。
答案2
set -e
如果你完全放弃并使用类似的东西会更容易
should-fail && exit 1
should-succeed || exit 1
在上面的代码中,should-fail
预期会失败,如果失败,脚本将以非零退出代码退出。
第二个预计会成功,如果没有成功,脚本就会退出。
或者,如果您希望 AND-OR 列表的使用保持一致,
! should-fail || exit 1
should-succeed || exit 1
或者
should-fail && exit 1
! should-succeed && exit 1
对于任何需要的不仅仅是简单的exit
如果失败的话,我会使用
if should-fail; then
# handle failure in test
exit 1
fi
if ! should-succeed; then
# handle failure in test
exit 1
fi
正如您已经注意到的,在set -e
active 状态下,如果命令的退出状态被 反转,shell 不会退出!
。这是 POSIX 的要求。以下内容来自特殊内置实用程序的 POSIX 规范set
,我强调:
执行 、 、、或保留字
-e
后面的复合列表时,应忽略该设置,while
until
if
elif
!
以保留字开头的管道,或 AND-OR 列表中除最后一个以外的任何命令。