为什么要测试" $?"一个反模式,看一个命令是否成功?

时间:2016-03-30 15:25:03

标签: bash

我看到here测试是否$?是零(成功)或其他东西(失败)是反模式,但我无法在其他任何地方找到它。

坚持Wikipedia的反模式的定义:"反模式(或反模式)是对反复出现的问题的常见反应,这种反复出现的问题通常是无效的,并且可能会产生高度适得其反的风险。 #34;为什么这会是反模式?

1 个答案:

答案 0 :(得分:10)

这是一个反模式,因为如果您根本不需要记录退出状态,它会引入不存在的复杂性。

if your_command; then ...

更容易出错
your_command
if [ "$?" -eq 0 ]; then ...

有关可能出错的事情的示例:请考虑添加traps,甚至添加新的echo语句以进行调试,修改$?。对于读者来说,运行your_command的单独行不能在不改变逻辑流的情况下添加任何内容,这在视觉上并不明显。

那是:

your_command
echo "Finished running your_command" >&2
if [ "$?" -eq 0 ]; then ...

...正在检查 echo ,而不是实际的命令。

因此,如果你真的需要以比它的值是否为零的更精细的方式处理退出状态,你应该在同一行收集它:

# whitelisting a nonzero value for an example of when "if your_command" won't do.
your_command; your_command_retval=$?
echo "Finished running your_command" >&2 ## now, adding more logging won't break the logic.
case $your_command_retval in
  0|2) echo "your_command exited in an acceptable way" >&2;;
  *)   echo "your_command exited in an unacceptable way" >&2;;
esac

最后:如果您将your_command括在if语句中,则会将其标记为已测试,这样您的shell就不会将非零退出状态视为目的set -eERR陷阱。

因此:

set -e
your_command
if [ "$?" -eq 0 ]; then ...

......永远不会(除了一些困扰set -e行为的角落案例和警告)以{{1}的任何值到达if语句除了$?之外,因为0会在这种情况下强制退出。相比之下:

set -e

...标记了set -e if your_command; then ... 经过测试的退出状态,因此不会认为这会导致脚本按your_command退出。