带有 `set -e` 的 Bash 脚本不会在 `... && ...` 命令上停止

907*_*7th 17 shell bash shell-script

我使用set -e的第一个错误停止bash脚本

一切正常,除非我使用命令&&

$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$
Run Code Online (Sandbox Code Playgroud)

和....相比:

$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$
Run Code Online (Sandbox Code Playgroud)

第一个例子仍然 echo I'm running!,但第二个没有。为什么他们的行为不同?

更新。类似问题:https : //stackoverflow.com/questions/6930295/set-e-and-short-tests

G-M*_*ca' 13

这是记录在案的行为。该庆典(1)手册页说,对set?-e

如果失败的命令是紧跟在所述命令列表的一部分的壳不退出whileuntil关键字,继该测试的一部分ifelif保留字, 在执行任何命令的一部分&&||列表 以外的命令之后的最终&&||,任何管道中的命令但最后一个,或者如果命令的返回值被!.
[强调。]

并且POSIX Shell 命令语言规范 确认这是正确的行为:

-e设置应执行以下化合物列表时被忽略whileuntilif,或elif保留字,管道期初!保留字,或小于最后的其他与或列表的任何命令。

第 2.9.3 节该文件的列表定义了

AND-OR 列表是由运算符“ &&”和||“ ? ”分隔的一个或多个管道的序列。


cuo*_*glm 10

set -e选项在某些情况下无效,这是标准行为,可在兼容 POSIX 的 shell 中移植。


失败的命令是管道的一部分:

false | true; echo printed
Run Code Online (Sandbox Code Playgroud)

将打印printed

并且只考虑管道本身的故障:

true | false; echo 'not printed'
Run Code Online (Sandbox Code Playgroud)

不会打印任何内容。


失败的命令在while, until, if,elif保留字后的复合列表中运行,以保留字开头的管道!,或作为除最后一个之外的任何命令的一部分&&||列表:

false || true; echo printed
Run Code Online (Sandbox Code Playgroud)

最后一条命令失败仍然使set -e受影响:

true && false; echo 'not printed'
Run Code Online (Sandbox Code Playgroud)

所述壳层中的化合物命令失败:

(false; echo 'not printed') | cat -; echo printed
Run Code Online (Sandbox Code Playgroud)

  • 请注意,`set -e` 会导致 `(false && true); 退出。echo 不在此处`,但不在`{ false && true; 中 }; echo here`,虽然 YMMV 具有不同的外壳,甚至同一个外壳的不同版本。我不会用驳船杆触碰`set -e`,而是会进行适当的错误处理。 (3认同)