エラーが発生したときにBashで行番号を見つけるにはどうすればよいですか?


21

エラーが発生した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


set -xおよび/またはset -vを使用して、実行された内容をトレースできます。正確にはあなたが求めたものではありませんが、おそらく役に立つでしょう。
ロルフ

回答:


29

関数を使用するのではなく、代わりにこのメソッドを使用します。

$ 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コマンドで関数を呼び出すことで機能します。

ここで私は、ファイルを作成するために、任意の注意を払っていませんでした、f1f2f3、またはf4。上記のスクリプトを実行すると:

$ ./yael.bash
cp: cannot stat f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"

失敗し、実行された行番号とコマンドを報告します。


14

LINENO現在の行番号を含むことに加えて、関数名とそれらが呼び出された行番号を含むBASH_LINENOand 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などに関する問題については、以下を参照してください。


13

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(リダイレクトなどはありません)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.