有人可以在下面的代码片段中解释bash / set -e行为吗?
#!/bin/bash
# Comment if you want to test the trap only
set -e -o pipefail -u -E
# Comment if you want to test the set -e only
trap "echo ERROR CAUGHT; exit 12" ERR
function reproduce() {
# Trigger arithmetic error on purpose
a=$((1109962735 - hello=12272 + 1))
}
reproduce
# The script is expected to trigger the trap and/or activate the set -e. In both cases it should stop and exit here on error.
status_code=$?
echo "STATUS ${status_code}"
if [[ "${status_code}" != "0" ]];then
echo "FIXME: why was status code not caught by set -e ?"
echo "Executing false to prove set -e is still active"
false
# If the following is not executed then it proves -e is still active
echo "set -e not active !!!!!"
exit 2
fi
这是执行时获得的结果:
$ bash reproduce.sh
reproduce.sh: line 8: 1109962735 - hello=12272 + 1: attempted assignment to non-variable (error token is "=12272 + 1")
STATUS 1
FIXME: why was status code it not caught by set -e ?
Executing false to prove set -e is still active
ERROR CAUGHT
检查退出代码
$ echo $?
1
重击版本
bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
转载也
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
与注释有关的其他注释(无论如何都要感谢所有建议):
让我们简化一下;重现您正在处理的问题所需的最少代码量为
set -e
: $((+)) # arithmetic expansion error
echo survived
根据标准,这绝不应该打印survived
,它说非交互式运行的POSIX shell应该在发生扩展错误时立即退出。但是貌似Bash并不这么认为。尽管此差异未在手册页中明确记录,但在POSIX模式的描述中却说
- 如果算术扩展中的语法错误导致表达式无效,则会退出非交互式外壳程序。
我们可以说这意味着在其默认操作模式下,非交互式Bash会话不会在此类错误时退出,但是正如您所意识到的,它也不会触发errexit机制或ERR陷阱。而是将非零值分配给继续$?
前进。
为了克服这个问题并获得预期的行为,您应该定义reproduce
如下
function reproduce() (
# Trigger arithmetic error on purpose
a=$((1109962735 - hello=12272 + 1))
)
这样,扩展错误将在子shell中发生,并使其以非零状态退出,因此errexit和trap将能够捕获该错误。
根据dash-o的请求,这是一个a
在表达式有效时为当前执行环境设置的版本
function reproduce() {
if : $((expression)); then
a=$((expression))
fi
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句