这是一个老问题,但这里没有一个答案讨论在Debian包处理脚本中使用 set -e aka set -o errexit . 根据Debian政策,这些脚本中必须使用此选项;意图显然是为了避免任何未处理错误情况的可能性 .
这在实践中意味着您必须了解在什么条件下运行的命令可能会返回错误,并明确地处理每个错误 .
常见的问题是例如 diff (当存在差异时返回错误)和 grep (当没有匹配时返回错误) . 您可以通过显式处理来避免错误:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2(另请注意我们如何注意在消息中包含当前脚本的名称,以及将诊断消息写入标准错误而不是标准输出 . )
如果没有真正必要或有用的显式处理,请明确地不做任何事情:
diff this that || true
grep cat food || :(使用shell的 : no-op命令有点模糊,但很常见 . )
重申一下,
something || other
是简写
if something; then
: nothing
else
other
fi
即,当且仅当 something 失败时,我们明确地说 other 应该运行 . longhand if (以及其他shell流控制语句,如 while , until )也是处理错误的有效方法(事实上,如果不是这样,带有 set -e 的shell脚本永远不会包含流控制语句!)
而且,只是为了明确,在没有像这样的处理程序的情况下,如果 diff 找到差异,或者 grep 找不到匹配项, set -e 将导致整个脚本立即失败并显示错误 .
另一方面,有些命令不希望他们这样做 . 通常有问题的命令是 find (退出状态不反映文件是否实际被发现)和 sed (退出状态不会显示脚本是否接收到任何输入或实际上是否成功执行了任何命令) . 在某些情况下,一个简单的保护是管道输出一个命令,如果没有输出就会尖叫:
find things | grep .
sed -e 's/o/me/' stuff | grep ^应该注意,管道的退出状态是该管道中最后一个命令的退出状态 . 所以上面的命令实际上完全掩盖了 find 和 sed 的状态,只告诉你 grep 是否最终成功 .
(当然,Bash有 set -o pipefail ;但Debian软件包脚本不能使用Bash功能 . 该策略坚决要求对这些脚本使用POSIX sh ,但情况并非总是这样 . )
在许多情况下,这是在防御性编码时要单独注意的事情 . 有时您必须例如浏览一个临时文件,这样你就可以看到生成该输出的命令是否成功完成,即使成语和方便还会指导你使用shell管道 .
















