如何在 Bash 中针对逻辑表达式中未处理的运行时错误进行防御性编码?

如何在 Bash 中针对逻辑表达式中未处理的运行时错误进行防御性编码?

我刚刚遇到一个错误,脚本中缺少一个函数。我已经trap提出了这些异常以提前停止脚本,但我注意到这并没有发生。进一步研究这一点,我发现作为逻辑表达式一部分发生的错误被认为是该表达式的一部分,而不是错误本身。

例如,请参阅此片段:

function _raise_error() {
    >&2 echo "Error on line $1"
}

trap '_raise_error $LINENO' ERR

# STDERR: _missing_function: command not found
_missing_function && echo "This expression is never true"

echo "This is printed, because the missing function error is not trapped"

是否有更好的方法来更具防御性地编写此代码,以使脚本在逻辑表达式中缺少函数时提前结束?我不确定如何捕捉这一点。在这种情况下使用set -e并没有什么区别,因为我已经捕获了错误并终止了脚本。

我最好的猜测是我需要将线路换行false。这不太理想,但我想不出更好的方法。

_missing_function && { echo "This expression is never true"; } || false

答案1

对于该特定错误,您可以执行以下操作:

$ cat tst.sh
#!/usr/bin/env bash

_raise_error() {
    echo "Error on line $1" >&2
}

command_not_found_handle() {
    _raise_error "${BASH_LINENO[0]}"
    kill -SIGUSR1 "$$"
}

trap '_raise_error "$LINENO"' ERR
trap 'exit 127' SIGUSR1

_missing_function && echo "This expression is never true"

echo "This is printed, because the missing function error is not trapped"

$ ./tst.sh
Error on line 15

或者,如果您只想_raise_error()从陷阱调用并让它执行以下操作exit

$ cat tst.sh
#!/usr/bin/env bash

_raise_error() {
    echo "Error on line $1" >&2
    exit "$2"
}

command_not_found_handle() {
    echo "${BASH_LINENO[0]}" > "$tmpCnf"
    kill -SIGUSR1 "$$"
    return 127
}

tmpCnfh=$(mktemp) || exit
trap 'rm -f "$tmpCnfh"; exit' EXIT
trap '_raise_error "$LINENO" "$?"' ERR
trap 'es="$?"; _raise_error "$(<"$tmpCnfh")" "$es"' SIGUSR1

_missing_function && echo "This expression is never true"

echo "This is printed, because the missing function error is not trapped"

$ ./tst.sh
Error on line 19

欲了解更多信息,请参阅:

相关内容