我似乎遇到了一个非常非常奇怪的不一致方式,dash
并使用该选项bash
检查错误情况。errexit
使用dash
和bash
不使用set -e
/set -o errexit
选项,以下程序:
foo()
{
echo pre
bar=$(fail)
echo post
}
foo
将打印以下内容(对于 的错误字符串略有不同dash
):
pre
./foo.sh: line 4: fail: command not found
post
使用该errexit
选项,它将打印以下内容:
pre
./foo.sh: line 4: fail: command not found
然而,令人惊讶的是,如果bar
是local
,程序将始终echo
同时具有pre
和post
。更具体地说,同时使用dash
和bash
不使用我们的errexit
选项,以下程序:
foo()
{
echo pre
local bar=$(fail)
echo post
}
foo
将打印以下内容:
pre
./foo.sh: line 4: fail: command not found
post
换句话说,似乎没有检查分配给局部变量的命令替换的返回值errexit
,但如果变量是全局的,则检查。
如果两个外壳都没有发生这种情况,我会倾向于认为这只是一个极端情况下的错误。由于dash
专门设计为符合 POSIX 标准,我想知道这种行为是否实际上是由 POSIX 标准指定的,尽管我很难想象这将如何有意义。
dash(1)
有这个要说的errexit
:
如果不是交互式的,如果任何未经测试的命令失败,则立即退出。如果命令用于控制
if
、elif
、while
或until
; ,则认为命令的退出状态是经过显式测试的。或者如果命令是“&&”或“||”的左侧操作数 操作员。
bash(1)
有点冗长,但我很难理解它:
如果 a
pipeline
(可能由单个simple command
)、 alist
或 acompound command
(见SHELL GRAMMAR
上文)以非零状态退出,则立即退出。while
如果失败的命令是紧跟在oruntil
关键字之后的命令列表的一部分、在if
or保留字之后的测试的一部分、在or列表elif
中执行的任何命令的一部分(除了最后or之后的命令),则 shell 不会退出管道中的命令但最后一个,或者如果命令的返回值与. 如果子 shell 以外的复合命令由于命令在被忽略时失败而返回非零状态,则 shell 不会退出。一个陷阱&&
||
&&
||
!
-e
ERR
,如果设置,则在 shell 退出之前执行。此选项分别适用于 shell 环境和每个子 shell 环境(见COMMAND EXECUTION ENVIRONMENT
上文),并可能导致子 shell 在执行子 shell 中的所有命令之前退出。如果复合命令或 shell 函数在
-e
被忽略的上下文中执行,则在复合命令或函数体中执行的任何命令都不会受到-e
设置的影响,即使-e
设置了并且命令返回失败状态。如果复合命令或 shell 函数在被忽略-e
的上下文中执行时-e
设置,则在复合命令或包含函数调用的命令完成之前,该设置将不起作用。