为了安全起见,我希望 bash 在遇到语法错误时中止脚本的执行。
令我惊讶的是,我无法实现这一点。 (set -e
还不够。)示例:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
结果(bash-3.2.39 或 bash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
好吧,我们无法$?
在每个语句之后进行检查以捕获语法错误。
(我期望从明智的编程语言中获得如此安全的行为......也许这必须作为错误/愿望报告给 bash 开发人员)
更多实验
if
没有什么区别。
删除if
:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
结果:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
也许,它与练习 2 有关http://mywiki.wooledge.org/BashFAQ/105和有关系(( ))
。但我发现语法错误后继续执行仍然不合理。
不,(( ))
没有什么区别!
即使没有算术测试,它的表现也很糟糕!只是一个简单的基本脚本:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
结果:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
答案1
将整体包装到一个函数中似乎可以解决问题:
#!/bin/bash -e
main () {
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
}
main "$@"
结果:
$ ./sh-on-syntax-err
$ ./sh-on-syntax-err line 6: #: syntax error: operand expected (error token is "#")
$
虽然我不知道为什么 - 也许其他人可以解释?
答案2
您可能误解了 的真正含义set -e
。仔细阅读help set
显示的输出:
-e Exit immediately if a command exits with a non-zero status.
-e
关于退出状态也是如此命令非零,与脚本中的语法错误无关。
一般来说,使用 被认为是不好的做法set -e
,因为所有错误(即命令的所有非零返回)都应该由脚本巧妙地处理(考虑健壮的脚本,而不是在输入带有空格或以连字符开头)。
根据语法错误的类型,脚本甚至可能根本不会执行。我对 bash 的了解不够,无法告诉确切地哪类语法错误(如果可以分类的话)可能会导致脚本立即中止。也许一些 Bash 专家会加入并澄清一切。
我只希望我澄清了这个set -e
声明!
关于您的愿望:
我期望从明智的编程语言中获得如此安全的行为......也许这必须作为错误/希望向 bash 开发人员报告
答案是肯定的不!正如您所观察到的那样(set -e
没有如您所期望的那样做出响应)实际上有很好的记录。
答案3
您可以通过放置类似的内容来使脚本检查自身
bash -n "$0"
靠近脚本顶部——set -e
任何重要代码之前但之后。
我不得不说,这感觉不太稳健,但如果它对你有用,也许是可以接受的。