関数を使用するのではなく、代わりにこのメソッドを使用します:
$ cat yael.bash
#!/bin/bash
set -eE -o functrace
file1=f1
file2=f2
file3=f3
file4=f4
failure() {
local lineno=$1
local msg=$2
echo "Failed at $lineno: $msg"
}
trap 'failure ${LINENO} "$BASH_COMMAND"' ERR
cp -- "$file1" "$file2"
cp -- "$file3" "$file4"
これは、ERR をトラップしてから failure()
を呼び出すことで機能します。 現在の行番号 + 実行された bash コマンドで機能します。
例
ここでは、ファイル f1
を作成することに何の注意も払っていません。 、 f2
、 f3
、または f4
.上記のスクリプトを実行すると:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
これは失敗し、行番号と実行されたコマンドが報告されます。
LINENO
に加えて 現在の行番号を含む BASH_LINENO
そして FUNCNAME
(そして BASH_SOURCE
) 関数名と呼び出し元の行番号を含む配列。
したがって、次のようなことができます:
#!/bin/bash
error() {
printf "'%s' failed with exit code %d in function '%s' at line %d.\n" "${1-something}" "$?" "${FUNCNAME[1]}" "${BASH_LINENO[0]}"
}
foo() {
( exit 0 ) || error "this thing"
( exit 123 ) || error "that thing"
}
foo
印刷する実行
'that thing' failed with exit code 123 in function 'foo' at line 9.
set -e
を使用する場合 、または trap ... ERR
エラーを自動的に検出するには、いくつかの注意事項があることに注意してください。また、スクリプトがその時点で何をしていたかの説明を含めることも困難ですが (あなたの例で行ったように)、通常のユーザーにとっては単なる行番号よりも役立つかもしれません.
例を参照してください。これらは set -e
に関する問題です その他:
- 括弧 () の後に OR リスト || が続くサブシェル内で set -e が機能しないのはなぜですか?
- let または expr が 0 に評価されると bash -e が終了します
- BashFAQ 105:set -e (または set -o errexit または trap ERR) が期待どおりに動作しないのはなぜですか?
Bash には組み込み変数 $LINENO
があります これは、ステートメント内では現在の行番号に置き換えられるため、次のことができます
in_case_fail $? "at $LINENO: cp $file1 $file2"
trap ... ERR
を使用することもできます コマンドが失敗したときに実行されます (結果がテストされていない場合)。例:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
次に、cp $file1 $file2
のようなコマンドの場合 失敗すると、行番号と終了を含むエラー メッセージが表示されます。また、変数 $BASH_COMMAND
にエラーのあるコマンドがあります。 (ただし、リダイレクトなどはありません)。