論理式で処理されていないランタイムエラーに対して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

詳細については、次を参照してください。

関連情報