如何使 bash 在语法错误时中止脚本的执行?

如何使 bash 在语法错误时中止脚本的执行?

为了安全起见,我希望 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任何重要代码之前但之后。

我不得不说,这感觉不太稳健,但如果它对你有用,也许是可以接受的。

相关内容