为什么测试"$"?看看命令是否成功,反模式? [英] Why is testing "$?" to see if a command succeeded or not, an anti-pattern?

查看:69
本文介绍了为什么测试"$"?看看命令是否成功,反模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在此处看到该测试是否为$?为零(成功)或其他内容(失败)是反模式,但我无法在其他任何地方找到它.

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 ,这样您的外壳程序就不会出于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语句>,因为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆