Bash if语句语法错误为何返回0?如何触发非零退出?
解决Bash中if测试语法错误导致静默成功的问题
先看这段存在拼写错误的Bash代码:
if [ "$a" = "foo"] then echo "TRUE" fi echo $?
执行后输出如下:
bash: [: missing `]' 0
可以看到,因为"foo"和]之间缺少空格的语法错误,[测试命令直接报错,但整个if语句的退出码却仍是0(表示执行成功)。这种静默错误很容易被忽略,存在不小的风险。
错误原因
Bash中if语句的退出码由最后执行的分支决定:当测试命令执行失败时,不会进入then分支,此时if语句默认返回0,因为没有执行任何失败的分支代码。
解决方法
- 改用扩展测试命令
[[
Bash的[[是扩展的条件测试语法,对格式要求更严格,遇到类似缺少空格的语法错误时,会直接让测试命令返回非零退出码,进而让整个if语句的退出码为非零。修改后的代码示例:
if [[ "$a" = "foo"]] then echo "TRUE" fi echo $?
执行时会直接报错,且退出码为非零,不会出现静默成功的情况。
开启Bash严格模式
在脚本开头添加set -euo pipefail,开启严格执行模式:set -e:命令执行失败(退出码非零)时立即终止脚本;set -u:引用未定义变量时直接报错;set -o pipefail:管道中任意命令失败时,整个管道的退出码为该命令的退出码。
开启后,当[命令因语法错误报错时,脚本会直接终止,避免后续代码继续执行。
单独捕获测试命令的退出码
把测试命令单独执行并捕获其退出码,再进行判断,这样就能拿到测试命令的真实退出状态:
[ "$a" = "foo"] test_exit_code=$? if [ $test_exit_code -eq 0 ]; then echo "TRUE" fi echo $test_exit_code
如果测试命令报错,test_exit_code会是非零值,不会被if语句的默认行为覆盖。
内容的提问来源于stack exchange,提问作者Seriously
相关产品推荐
相关产品推荐

