为了账号安全,请及时绑定邮箱和手机立即绑定

为什么要测试“ $?”以查看命令是否成功(反模式)?

为什么要测试“ $?”以查看命令是否成功(反模式)?

慕虎7371278 2019-11-20 14:18:05
我在这里看到测试是否为$?为零(成功)或其他内容(失败)是反模式,但是我无法在其他任何地方找到它。坚持Wikipedia的反模式定义:“反模式(或反模式)是对反复出现的问题的普遍反应,该问题通常无效,并且具有适得其反的风险。” 为什么这会是反模式?
查看完整描述

3 回答

?
莫回无

TA贡献1865条经验 获得超7个赞

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


if your_command; then ...

出错的几率比


your_command

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

有关可能出错的示例:考虑陷阱,甚至考虑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 -e或ERR陷阱。


从而:


set -e

your_command

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

...将永远不会(除非有许多困扰set -e行为的极端情况和警告)if以$?除以外的其他任何值到达该语句0,因为set -e在这种情况下将强制退出。相比之下:


set -e

if your_command; then ...

...将标记your_command为已测试的退出状态,因此不认为它会导致脚本强制退出per set -e。


查看完整回答
反对 回复 2019-11-20
?
杨__羊羊

TA贡献1943条经验 获得超7个赞

“通常无效”是该定义中经过深思熟虑的组成部分。如果有一种最佳实践替代方案可以解决主要陷阱或警告,而又没有任何负面折衷,则某些事情可能在超过50%的时间工作时成为反模式。确实,一些反模式之类的东西之所以如此,是因为它们带来了安全风险。一个安全漏洞只需要利用一次就可以使具有该漏洞的代码不可接受,而不是超过50%的执行。

查看完整回答
反对 回复 2019-11-20
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

经过这么多年的软件编写,除了在早期开发工作中我对调试用输出感兴趣的情况下,我不会使用错误的格式。如前所述,不要增加不必要的复杂性。

查看完整回答
反对 回复 2019-11-20
  • 3 回答
  • 0 关注
  • 601 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信