What does set -e mean in a bash script?
我正在研究这个preinst文件的内容,在从debian存档(.deb)文件中解包包包之前脚本会执行这个文件。
脚本包含以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash set -e # Automatically added by dh_installinit if ["$1" = install ]; then if [ -d /usr/share/MyApplicationName ]; then echo"MyApplicationName is just installed" return 1 fi rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf rm -Rf $HOME/.local/share/file-manager/actions/* fi # End automatically added section |
我的第一个查询是关于行:
1 | set -e |
我认为脚本的其余部分非常简单:它检查debian/ubuntu包管理器是否正在执行安装操作。如果是,它会检查我的应用程序是否刚刚安装在系统上。如果有,脚本将打印消息"myapplicationname is just installed"并结束(
如果用户要求debian/ubuntu软件包系统安装我的软件包,脚本也会删除两个目录。
这是对的还是我错过了什么?
From
1 | -e Exit immediately if a command exits with a non-zero status. |
但有些人(Bash Faq and people writing this faq on IRC freenode ;Bash)认为这是坏的做法:
ZZU1
当出现错误时运行函数。
See http://mywiki.wooledge.org/bashfaq/105
如果命令或管道有误,请停止脚本的执行,因为这是防御壳牌行为的对立,而这是脚本中的错误。在一个终端看到这座建筑物的文档。
如果一条管道由一个单一的简单命令、一份清单或一个复合命令返回一个非零状态组成,则该管道即可立即出口。
根据Default,管道的出口状态是管道中最后一个命令的出口状态,但不包括EDOCX1&6)。
如果这样,管道最后(右)状态的回报以一个非零状态存在,或如果所有指挥官都成功的话,则以零状态存在。
如果你想在出口上执行一些事情,试试定义
1 | trap onexit EXIT |
复制这个网站码到您的网站上以设置一个投票箱在您的网站上。
1 | onexit(){ while caller $((n++)); do :; done; } |
有类似的选择:
1 | trap onerr ERR |
Examples
零状态示例:
1 2 | $ true; echo $? 0 |
Non-零status example:
1 2 | $ false; echo $? 1 |
Negating Status Examples:
1 2 3 4 | $ ! false; echo $? 0 $ false || true; echo $? 0 |
测试与EDOCX1&6
1 2 3 4 5 6 7 8 | $ bash -c 'set +o pipefail -e; true | true | true; echo success'; echo $? success 0 $ bash -c 'set +o pipefail -e; false | false | true; echo success'; echo $? success 0 $ bash -c 'set +o pipefail -e; true | true | false; echo success'; echo $? 1 |
与
1 2 | $ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $? 1 |
我发现这个问题是在古灵试图找出由于一个
例如,假设我有一个壳牌
1 2 3 4 | #!/bin/sh set -e ./inner-test.sh exit 62; |
The Code for
1 2 | #!/bin/sh exit 26; |
当我运行时,从指挥线我的外脚本终结者与内幕的出口代码:
1 2 3 | $ ./outer-test.sh $ echo $? 26 |
我认为,我们的目的是让这个剧本迅速失败。
要自己测试,只需在bash提示下键入
现在,要在"脚本"的上下文中理解这一点,请使用以下简单脚本:
1 2 3 4 5 6 | #!/bin/bash # set -e lsd ls |
如果按原样运行,您将在最后一行从
这是一个古老的问题,但是这里的答案都没有讨论在debian包处理脚本中使用
这在实践中意味着,您必须了解在什么条件下运行的命令可能返回错误,并显式地处理每个错误。
常见的gotchas包括:
1 2 3 4 | diff this that || echo"$0: there was a difference">&2 grep cat food || echo"$0: no cat in the food">&2 |
(还要注意我们如何注意在消息中包含当前脚本的名称,以及如何将诊断消息写入标准错误而不是标准输出。)
如果没有真正必要或有用的显式处理,则显式不执行任何操作:
1 2 | diff this that || true grep cat food || : |
(Shell的
只是重申一下,
1 | something || other |
是
1 2 3 4 5 | if something; then : nothing else other fi |
也就是说,我们明确地说,只有当
而且,更明确地说,在没有这样的处理程序的情况下,如果
另一方面,有些命令在您希望的时候不会产生错误退出状态。通常有问题的命令是
1 2 | find things | grep . sed -e 's/o/me/' stuff | grep ^ |
应该注意,管道的退出状态是该管道中最后一个命令的退出状态。所以上面的命令实际上完全掩盖了
(当然,bash有
在许多情况下,当进行防御编码时,这是需要单独注意的事情。有时,您必须检查一个临时文件,以便可以看到生成该输出的命令是否成功完成,即使成语和方便性会指导您使用shell管道。