Ubuntu 12.04.2を使用しています。シェルスクリプトで例外やエラーをキャッチするために「trap」コマンドを使用しようとしていますが、手動で「error」出口をトリガーしようとしています。
Exit1を試しましたが、「エラー」シグナルは発生しません。
#!/bin/bash
func()
{
exit 1
}
trap "echo hi" INT TERM ERR
func
「エラー」終了信号を手動でトリガーする方法がわかりませんか?
答え1
トラップ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を受信したら終了することも考慮する必要があります。
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
答え2
関数が終了したときに状態を設定するには、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'
false
0 リターン、ERR トラップのアノテーション、ERR ハンドラから EXIT トラップをキャンセルしない、ERR ハンドラで終了しない、return を削除し、func の最後のステートメントにするなど、さまざまな変更を試すことができます。