有人可以在下面的代码片段中解释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 模式的描述中它说
- 如果算术扩展中的语法错误导致无效表达式,则非交互式 shell 退出。
我们可以说,这意味着在其默认操作模式下,非交互式 Bash 会话不会因此类错误而退出,但正如您所意识到的,它也不会触发 errexit 机制或 ERR 陷阱。$?相反,它为继续移动分配一个非零值。
为了克服这个问题并获得预期的行为,您应该定义reproduce如下
function reproduce() (
    # Trigger arithmetic error on purpose
    a=$((1109962735 - hello=12272 + 1))
)
这样,扩展错误将发生在子 shell 中,并导致它以非零状态退出,因此 errexit 和 trap 将能够捕获它。
a根据 dash-o 的要求,这里是当表达式有效时为当前执行环境设置的版本
function reproduce() {
    if : $((expression)); then
        a=$((expression))
    fi
}
| 归档时间: | 
 | 
| 查看次数: | 98 次 | 
| 最近记录: |