如何避免Bash中嵌套函数的执行失败被遗漏?
关于Bash中errexit与函数退出码传递的问题
问题复现
执行以下Bash代码:
#!/usr/bin/env bash set -Eeuo pipefail shopt -s huponexit shopt -s inherit_errexit function child_function { return 1 } function parent_function { child_function echo "parent noticed child exit code as $?" } function grandparent_function { local ec ec=0 && parent_function || ec="$?" echo "grandparent noticed parent exit code as $ec" } grandparent_function
得到意外输出:
parent noticed child exit code as 1 grandparent noticed parent exit code as 0
修复后的代码及结果
修改代码如下:
#!/usr/bin/env bash set -Eeuo pipefail shopt -s huponexit shopt -s inherit_errexit function child_function { return 1 } function parent_function { child_function || return "$?" echo "parent noticed child exit code as $?" } function grandparent_function { local ec ec=0 && parent_function || ec="$?" echo "grandparent noticed parent exit code as $ec" } grandparent_function
可得到预期结果:
grandparent noticed parent exit code as 1
疑问
这种情况需要设置额外参数解决吗?还是属于Bash的Bug?
原因分析
我认为这是Bug,理由如下:
当不使用|| ec="$?"这类错误捕获逻辑时,-e/errexit选项(命令非零退出时立即终止脚本)会正常生效,每个执行失败的函数都会直接退出:
#!/usr/bin/env bash set -Eeuo pipefail shopt -s huponexit shopt -s inherit_errexit function child_function { return 1 } function parent_function { child_function echo "parent noticed child exit code as $?" } function grandparent_function { parent_function echo "grandparent noticed parent exit code as $?" } grandparent_function
此时脚本无任何输出,且最终返回退出码1。但在使用ec=0 && parent_function || ec="$?"这种结构时,parent_function明明执行了失败的child_function却没有触发errexit退出,反而继续执行后续代码,最终导致grandparent_function捕获到的退出码为0,这不符合预期。
内容的提问来源于stack exchange,提问作者balupton
相关产品推荐
相关产品推荐

