Trapコマンドを使用してエラーをトリガーする方法


13

Ubuntu 12.04.2を使用しています。「トラップ」コマンドを使用してシェルスクリプトの異常またはエラーをキャプチャしようとしていますが、「エラー」終了を手動でトリガーしようとしています。

exit 1を試しましたが、「エラー」信号はトリガーされません。

#!/bin/bash

func()
{
    exit 1
}

trap "echo hi" INT TERM ERR
func

「エラー」終了信号を手動でトリガーする方法がわからない場合

回答:


20

ERRトラップは、シェル自体が非ゼロのエラーコードで終了したときにコードを実行し、それだけにはされていない場合に任意のコマンドの一部ではないことをシェルによって実行条件(のようにif cmd...、またはcmd || ...非ゼロの...)終了終了ステータス(set -eシェルを終了する原因と同じ条件)。

ゼロ以外の終了ステータスでシェルの終了時にコードを実行する場合は、EXIT代わりにトラップを追加して確認する必要$?があります。

trap '[ "$?" -eq 0 ] || echo hi' EXIT

ただし、トラップされたシグナルでは、シグナルトラップとEXITトラップの両方が実行されるため、次のようにすることができます。

unset killed_by
trap 'killed_by=INT;exit' INT
trap 'killed_by=TERM;exit' TERM
trap '
  ret=$?
  if [ -n "$killed_by" ]; then
    echo >&2 "Ouch! Killed by $killed_by"
    exit 1
  elif [ "$ret" -ne 0 ]; then
    echo >&2 "Died with error code $ret"
  fi' EXIT

または$((signum + 128))、シグナルのような終了ステータスを使用するには:

for sig in INT TERM HUP; do
  trap "exit $((128 + $(kill -l "$sig")))" "$sig"
done
trap '
  ret=$?
  [ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"' EXIT

ただし、親プロセスが、端末割り込みの待機および協調終了処理bashを実装するシェルのような場合、SIGINTまたはSIGQUITで正常に終了すると、迷惑な副作用が生じる可能性があることに注意してください。そのため、実際に中断されたことを親に報告し、SIGINT / SIGQUITを受信した場合は自分自身を終了することも考慮するように、代わりに同じ信号で自分自身を殺すようにしてください。

unset killed_by
for sig in INT QUIT TERM HUP; do
  trap "exit $((128 + $(kill -l "$sig"))); killed_by=$sig" "$sig"
done
trap '
  ret=$?
  [ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"
  if [ -n "$killed_by" ]; then
    trap - "$killed_by" # reset handler
    # ulimit -c 0 # possibly disable core dumps
    kill -s "$killed_by" "$$"
  else
    exec "$ret"
  fi' EXIT

ERRトラップを起動する場合は、falseまたはなどのゼロ以外の終了ステータスでコマンドを実行し testます。


6

関数の終了時にステータスを設定するには、exitではなくreturnを使用します(関数がreturnなしでフォールスルーする場合、ステータスは最後に実行されたステートメントのステータスになります。)質問の例の代わりにreturn使用exitすると、私はあなたが意図したと思う:トラップはERR疑似信号でトリガーされ、「hi」が出力されます。その他の考慮事項については、これを試してください:

#!/bin/bash

func()
{
    echo 'in func'
    return 99
    echo 'still in func'
}

trap 'echo "done"' EXIT
trap 'status=$?; echo "error status is $status"; trap - EXIT; exit $status' ERR
func
echo 'returned from func'

0を返す、ERRトラップをコメントアウトする、ERRハンドラー内でEXITトラップをキャンセルしない、ERRハンドラーを終了しない、リターンを削除falseしてfuncの最後のステートメントとして置くなど、さまざまな変更を試すことができます。

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