题 set -e在bash脚本中的含义是什么?


我正在研究这个内容 PREINST 脚本在从Debian存档(.deb)文件解压缩之前执行的文件。

该脚本具有以下代码:

#!/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

我的第一个问题是关于这一行:

set -e

我认为脚本的其余部分非常简单:它检查Debian / Ubuntu包管理器是否正在执行安装操作。如果是,则检查我的应用程序是否刚刚安装在系统上。如果有,脚本将打印该消息 “MyApplicationName刚刚安装” 并结束(return 1 意味着以“错误”结束,不是吗?)。

如果用户要求Debian / Ubuntu软件包系统安装我的软件包,该脚本还会删除两个目录。

这是对的还是我错过了什么?


415
2017-10-27 19:06


起源


设置-e - Anders Lindahl
为什么你在谷歌中找不到这个:你的查询中的-e被解释为否定。请尝试以下查询:bash set“-e” - Maleev
@twalberg当我问自己同样的问题时,我在看 man set - Sedat Kilinc
如果您正在查看如何将其关闭,请将短划线换成加号前缀: set +e - Tom Saleeba
@twalberg但要求真正的人比仅仅提出机器人的请求更有趣;-)。 - vdegenne


答案:


help set :

  -e  Exit immediately if a command exits with a non-zero status.

但有些人认为这是一种不好的做法(bash常见问题解答,比如人们在irc freenode #bash上撰写此常见问题解答),更好地使用:

trap 'do_something' ERR

跑步 do_something 发生错误时的功能。

看到 http://mywiki.wooledge.org/BashFAQ/105


467
2017-10-27 19:39



如果我想要“如果命令以非零状态退出则立即退出”,那么do_something会是什么样的? - CMCDragonkai
trap 'exit' ERR - chepner
该 ERR trap函数不会继承trap,所以如果你有函数, set -o errtrace 要么 set -E 将允许您只设置一次陷阱并全局应用它。 - ykay
不 trap 'exit' ERR 做 什么 不同于 set -e? - Andy
如果这是不好的做法那么为什么它被用于 Debian包? - phuclv


set -e 如果命令或管道有错误,则停止执行脚本 - 这与默认shell行为相反,即忽略脚本中的错误。类型 help set 在终端中查看此内置命令的文档。


61
2017-10-27 19:14



它只会停止执行 持续 管道中的命令有错误。有一个Bash特定选项, set -o pipefail 可用于传播错误,以便如果前面的命令之一以非零状态退出,则管道命令的返回值不为零。 - Anthony Geoghegan


按照 bash - Set Builtin 手动,如果 -e/errexit 如果设置,shell会立即退出 管道 由一个单一组成 简单的命令一个列表 要么 复合命令 返回非零状态。

默认情况下,管道的退出状态是管道中最后一个命令的退出状态,除非 pipefail 选项已启用(默认情况下已禁用)。

如果是这样,管道的最后(最右边)命令的返回状态以非零状态退出,或者如果所有命令都成功退出则返回零。

如果您想在退出时执行某些操作,请尝试定义 trap, 例如:

trap onexit EXIT

哪里 onexit 是你在退出时做某事的功能,就像下面打印简单一样 堆栈跟踪

onexit(){ while caller $((n++)); do :; done; }

有类似的选择 -E/errtrace 这将陷入ERR,例如:

trap onerr ERR

例子

零状态示例:

$ true; echo $?
0

非零状态示例:

$ false; echo $?
1

否定状态示例:

$ ! false; echo $?
0
$ false || true; echo $?
0

测试用 pipefail 被禁用:

$ 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

测试用 pipefail 启用:

$ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $?
1

33
2017-12-20 13:31





我在谷歌搜索时发现了这个问题,试图找出由于a而被中止的脚本的退出状态 set -e。答案对我来说并不明显;因此这个答案。基本上, set -e 中止执行命令(例如shell脚本)并返回失败命令的退出状态代码(即内部脚本,而不是外部脚本)

例如,假设我有一个shell脚本 outer-test.sh

#!/bin/sh
set -e
./inner-test.sh
exit 62;

代码 inner-test.sh 是:

#!/bin/sh
exit 26;

当我跑 outer-script.sh 从命令行我的外部脚本终止与内部脚本的退出代码:

$ ./outer-test.sh
$ echo $?
26

25
2017-08-05 22:54