エラーが発生したBashの行番号をどのように見つけますか?
以下の簡単なスクリプトを行番号を付けて作成し、必要なものを説明します。スクリプトはからファイルをコピーします
cp $file1 $file2
cp $file3 $file4
cp
コマンドの1つが失敗すると、関数はexit 1で終了します。関数に機能を追加して、エラーを行番号(たとえば、8または12)で出力することもできます。
これは可能ですか?
1 #!/bin/bash
2
3
4 function in_case_fail {
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6 }
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
関数を使用するのではなく、代わりにこのメソッドを使用します。
_$ 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をトラップし、現在の行番号+実行されたbashコマンドを使用してfailure()
関数を呼び出すことで機能します。
ここでは、_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
などの問題:
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
にエラーのあるコマンドがあります(ただし、リダイレクトなどはありません)。