为什么使用模式“命令|| 真的”有用吗?


78

我目前正在研究Debian软件包,并且已经阅读了一些代码示例。例如,postinst脚本中的每一行都是一个模式。

some command || true
another command || true

因此,如果某些命令失败,则该行返回true,但我看不到这如何影响程序的输出。


5
仅供参考,这||:是另一种惯用的写法(:是内置表中的另一个条目,指向true-但保证是内置的,甚至可以返回到Bourne;也就是说,对于POSIX sh,true同样保证是内置的-因此甚至在遥远的现代时代都比效率更简洁)。
查尔斯·达菲

Answers:


151

这种模式的原因是Debian软件包中的维护者脚本倾向于以开头set -e,这会导致shell以任何非零状态退出的命令(严格来说,管道,列表或复合命令)退出。这样可以确保错误不会累积:一旦出现问题,脚本将中止。

如果允许脚本中的命令失败,则添加操作|| true可确保生成的复合命令始终以状态零退出,因此脚本不会中止。例如,删除目录不应该是致命的错误(防止删除软件包)。所以我们会用

rmdir ... || true

因为rmdir没有选择告诉它忽略错误。


4
好吧,set -e根本没有必要|| true,我认为提供上下文很重要。如果您在POWER上发现奇怪的地方,强烈建议您提交错误(reportbug)!
史蒂芬·基特

16
@MichaelFelt实际上set -e不仅是“ Debian约定”,而且应该始终使用一种好的编程模式。看到。例如davidpashley.com/articles/writing-robust-shell-scripts
kay

2
这里的每个问题-为什么使用|| trueset -e是可能的上下文,并且可能是最常见的。我鞠躬这个答案!不过,从字面上看,它在任何时候都认为退出状态无关紧要并且(如您的文章链接所添加的)任何时候都很有用。我没有将退出状态用作脚本控件的一部分。我看到了实用程序(在中set -e),但不会走那么远,而是说“您编写的每个脚本都应在顶部包含set -e”。这是一种编程风格。“ ALWAYS | Every”包括自己的陷阱集-aka-绝对值:通配符解决方案ALWAYS最终会事与愿违-没有免费乘车服务。
Michael Felt

1
@Kay这是当前流行的观点,但最终被众多限制脚本可移植性的假设所困扰。历史上与set -e行为不一致。如果您的唯一目标是bash,以及其他相对较新的Shell驻留在/bin/sh,这对您可能并不重要,但是当您想支持旧的Shell /系统时,情况就更加细微了。
mtraceur

2
@StephenKitt当然可以。Sven Mascheck提供了一个非常详尽的页面,记录了不同壳的set -e行为,尽管该页面还记录了许多与今天无关的历史/古代壳。还有这两个页面,它们的使用范围较窄(搜索“ set -e”):“ lintsh”页面autoconf的便携式shell文档->内置的限制子页面
mtraceur

32

尽管它不会影响程序的输出,但它会允许调用方继续进行,就好像一切正​​常,也影响了以后的逻辑一样。

改写:它掩盖了先前命令的错误状态

michael@x071:[/usr/sbin]cat /tmp/false.sh
#!/bin/sh
false

michael@x071:[/usr/sbin]cat /tmp/true.sh 
#!/bin/sh
false || true

michael@x071:[/usr/sbin]sh /tmp/false.sh; echo $?
1
michael@x071:[/usr/sbin]sh /tmp/true.sh; echo $? 
0

6
没错,但这并不能回答为什么屏蔽命令的退出状态很有用。
moopet

4
set -e表示脚本将在非零返回时立即终止。在那个本地化的地方,您可能不希望发生这种情况!
rackandboneman

我是一个简单的人-对我来说,掩盖错误状态的唯一原因是因为它“在路上”。如果您不关心,set -e会“顺便说说”任何错误。我喜欢讨论,因为我认为这是帮助调试脚本和编写其他逻辑以响应错误的好方法(例如||打印-“此处的xxx存在非零”。 shell函数“致命”,我有“某事||致命的”我不高兴”。恕我直言,脚本应该报告失败状态,或者不在乎。-e加|| true是掩盖错误。如果那是我想要的-很好,如果没有,我会漏掉错误
Michael Felt

我要问自己的是:true-编码拐杖(一种懒惰的方式来解决/过去我现在不想处理的错误;调试工具(-e但没有|| true),或者只是某人关于良好编码实践的教条。 -我认为这是一个特点-具有潜在的好处,我不认为这是一个魔术棒治愈所有总之- 。正如美在旁观者的眼睛- set -e|| true公用事业将由特征和目标确定程序员
Michael Felt

6
@MichaelFelt考虑:git remote remove foo || true git remote add foo http://blah-如果遥控器不存在,我们想忽略该错误。
immibis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.