为什么要测试“$?"?查看命令是否成功,反模式? [英] Why is testing "$?" to see if a command succeeded or not, an anti-pattern?
问题描述
我看到 这里 测试是否 $?是零(成功)还是其他(失败)是一种反模式,但我在其他任何地方都找不到.
I see here that testing whether $? is zero (success) or something else (failure) is an anti-pattern, but I have not been able to find this anywhere else.
坚持维基百科的反模式定义:一个反模式模式(或反模式)是对反复出现的问题的常见反应,通常是无效的,并且有可能适得其反."为什么这是一种反模式?
Sticking to the definition of anti-pattern of the Wikipedia: "An anti-pattern (or anti-pattern) is a common response to a recurring problem that is usually ineffective and risks being highly counterproductive." Why would this be an anti-pattern?
推荐答案
这是一种反模式,因为它引入了复杂性,如果您根本不需要记录退出状态就不会存在.
This is an antipattern because it introduces complexity that wouldn't exist if you didn't require the exit status to be recorded at all.
if your_command; then ...
出错的地方比
your_command
if [ "$?" -eq 0 ]; then ...
<小时>
关于可能出错的例子:想想陷阱,甚至新的echo
语句添加用于调试,修改 $?
.对于读者来说,在不改变逻辑流程的情况下,运行 your_command
的单独行不能在其下方添加任何内容,这在视觉上并不明显.
For examples of things that can go wrong: Think about traps, or even new echo
statements added for debugging, modifying $?
. It's not visually obvious to a reader that a separate line running your_command
can't have anything added below it without changing logical flow.
即:
your_command
echo "Finished running your_command" >&2
if [ "$?" -eq 0 ]; then ...
...正在检查 echo,而不是实际的命令.
...is checking the echo, not the actual command.
因此,如果您确实确实需要以比立即分支其值是否为零的方式更精细地处理退出状态,您应该在同一行收集它:>
Thus, in cases where you really do need to deal with exit status in a manner more granular than immediately branching on whether its value is zero, you should collect it on the same line:
# 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
语句中,这会将其标记为 tested,这样您的 shell 就不会考虑用于 set -e
或 ERR
陷阱的非零退出状态.
Finally: If you enclose your_command
inside of an if
statement, this marks it as tested, such that your shell won't consider a nonzero exit status for purposes of set -e
or an ERR
trap.
因此:
set -e
your_command
if [ "$?" -eq 0 ]; then ...
...永远不会(除了一些困扰set -e
行为的极端情况和警告)到达if
具有除 0
之外的任何 $?
值的语句,因为 set -e
在这种情况下将强制退出.相比之下:
...will never (barring a number of corner cases and caveats which plague set -e
's behavior) reach the if
statement with any value of $?
other than 0
, as the set -e
will force an exit in that case. By contrast:
set -e
if your_command; then ...
...将 your_command
的退出状态标记为已测试,因此不认为这会导致根据 set -e
强制退出脚本.
...marks the exit status of your_command
as tested, and so does not consider it cause to force the script to exit per set -e
.
这篇关于为什么要测试“$?"?查看命令是否成功,反模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!