Kir*_*rby 2 error-handling bash
我bash v4.4.12在 Debian 上进行了默认设置:
$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
Run Code Online (Sandbox Code Playgroud)
我更喜欢在我的脚本中使用这些选项:
set -o pipefail
set -o errexit
set -o nounset
Run Code Online (Sandbox Code Playgroud)
它使管道命令 ( ) 中的非零结果停止脚本pipefail,执行退出 ( errexit),并验证未设置的变量 ( nounset)。
我有测试脚本:
set -o pipefail
set -o errexit
set -o nounset
set -o xtrace
return_1() { return 22; }
test_1 () {
return_1;
echo 'after';
}
success_1() {
echo success
}
if [ "${1:-}" == 1 ]; then
# make "return 1" in the root level
return_1
fi
if [ "${1:-}" == 2 ]; then
# run test_1, we will get "return 1" within a function
test_1
fi
if [ "${1:-}" == 3 ]; then
# run test_1 and success_1 in chain
# success_1 MUST NOT be ran because test_1 makes non-zero status
# in fact, success_1 will be ran =(
test_1 && success_1
fi
Run Code Online (Sandbox Code Playgroud)
测试。
$ bash /test.sh 1; echo "status: ${?}"
+ '[' 1 == 1 ']'
+ return_1
+ return 22
status: 22
Run Code Online (Sandbox Code Playgroud)
按预期工作。
$ bash /test.sh 2; echo "status: ${?}"
+ '[' 2 == 1 ']'
+ '[' 2 == 2 ']'
+ test_1
+ return_1
+ return 22
status: 22
Run Code Online (Sandbox Code Playgroud)
一切都是对的。这行“回显‘之后’;” 没打电话。
$ bash /test.sh 3; echo "status: ${?}"
+ '[' 3 == 1 ']'
+ '[' 3 == 2 ']'
+ '[' 3 == 3 ']'
+ test_1
+ return_1
+ return 22
+ echo after
after
+ success_1
+ echo success
success
status: 0
Run Code Online (Sandbox Code Playgroud)
完全不对。:( 1. 行“echo 'after';”已调用。2. 函数“success_1”也已调用。
真的,这个案子到底是怎么回事?
UPD手册参考。
您已经陷入了使用set -e. 请仔细阅读为什么 set -e (或 set -o errexit 或 trap ERR)没有达到我的预期?
来自GNU bash文档set -e
while如果失败的命令是紧跟在oruntil关键字之后的命令列表的一部分、if 语句中测试的一部分、在&&or||列表中执行的任何命令的一部分(最后一个或后面的命令除外),&&则shell 不会退出。||
您认为这段代码会发生什么?
#!/usr/bin/env bash
set -e
test -d nosuchdir && echo no dir
echo survived
Run Code Online (Sandbox Code Playgroud)
自己运行它并观察为什么对使用或set -e运行的命令没有影响。您报告的第三个案例也发生了同样的情况。即使该函数返回非零退出代码,使用另一个函数作为 的一部分也会强制 shell 忽略该选项集。&&||test_1&&errorexit
最好避免set -e并使用您自己添加的错误检查。在这种情况下,在 if 条件中使用函数的返回码并对结果取反
if ! test_1; then
success_1
fi
Run Code Online (Sandbox Code Playgroud)
另请阅读Raise error in a Bash script,其中有一些关于如何在 shell 中以最佳方式处理错误的答案。