为什么模式“command || true”有用?

car*_*ter 98 shell-script error-handling

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

some command || true
another command || true
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*itt 174

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

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

rmdir ... || true
Run Code Online (Sandbox Code Playgroud)

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

  • @MichaelFelt,实际上`set -e` 不仅是“Debian 约定”,而且是一种应始终使用的良好编程模式。看。例如 http://www.davidpashley.com/articles/writing-robust-shell-scripts/ (20认同)
  • 好吧,没有`set -e` 就不需要`|| 完全正确,我认为提供上下文很重要。如果您在 POWER 上发现奇怪的事情,我强烈建议您提交错误 (`reportbug`)! (5认同)
  • 根据这里的问题 - 为什么使用`|| true` set -e 是可能的上下文,并且可能是最常见的。我向这个答案鞠躬!不过,从字面上看,只要退出状态被认为无关紧要并且(正如您文章链接所添加的那样)我没有将退出状态用作脚本控制的一部分,它就很有用。我看到了实用程序(在 `set -e` 中),但不会像文章那样说“你编写的每个脚本都应该在顶部包含 set -e”。这是一种编程风格。“ALWAYS | Every”包括它自己的一套陷阱——也就是——绝对的:通配符解决方案最终会“总是”适得其反——没有搭便车。 (2认同)
  • @StephenKitt 当然可以。有一个非常彻底的 [页面记录了 Sven Mascheck 的不同 shell 的`set -e` 行为](http://www.in-ulm.de/~mascheck/various/set-e/),尽管这个页面也记录了许多历史/古代贝壳今天无关紧要。还有这两个页面具有较窄的现代焦点(搜索“set -e”):[“lintsh”页面](http://code.dogmap.org/lintsh/),[autoconf 的便携式 shell 文档 -> 限制内置子页面](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Limitations-of-Builtins.html#Limitations-of-Builtins) (2认同)

Mic*_*elt 34

虽然它不会影响刚刚运行的程序的输出 - 它允许调用者继续进行,好像一切都好,也就是影响未来的逻辑。

改写:它掩盖了上一个命令的错误状态

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
Run Code Online (Sandbox Code Playgroud)

  • 这是真的,但它没有回答为什么屏蔽命令的退出状态很有用。 (6认同)
  • @MichaelFelt 考虑:`git remote remove foo || true` `git remote add foo http://blah` - 如果遥控器不存在,我们想忽略错误。 (6认同)
  • set -e 意味着脚本将在非零返回时立即终止。在那个本地化的地方,您可能不希望这种情况发生! (4认同)