以下を考慮してください。
#!/bin/bash
trap 'echo $?' INT
kill -INT $$
出力:0
ここで私は130
私のシステムを楽しみにしています。もちろん私がaをしたならCtrl + C
私は130
。
HUP
または同じ他の信号でも同様ですTERM
。trap
多くの信号をキャプチャする設定があると、ハンドラが呼び出された信号の正しいエラーコードで終了できないため、この動作は驚くべきことです。
#!/bin/dash
exit_abrupt() {
exit_code=$?
echo "Encountered an error, cleaning up..." >&2
# *clean up*
exit "$exit_code" # This will return 0!
}
trap exit_abrupt HUP INT TERM
kill -HUP $$
Bash、Dash、ZSHをテストしましたが、すべてこれらの動作を示しました。これがクロスシェルが機能する方法ですか? POSIXによって文書化されていますか(誰かが私に文書を教えてもらえますか?)シェルで実行するための正しい終了コードをどうやって知ることができますか?
最高POSIX ドキュメント私が読んだ内容は次のとおりです。
「$」の値は何ですか?トラップ操作の完了は、トラップが呼び出される前の値でなければなりません。
私にとっては、すべての場合に信号を伝える必要があるように聞こえますが、そうではないので、何かが欠けています。
ベストアンサー1
$?
最後のコマンドの実行と待機の終了状態が含まれます。以下で見つけることができます:
$ bash -c 'trap "echo \$?" INT; sleep 10; exit'
^C130
130 は ^Csleep
から SIGINT を受け取りbash
、bash が戻った後にハンドラーを実行し、コマンドsleep
の終了状況を印刷したため報告されました。sleep
存在する:
$ bash -c 'trap "echo \$?" INT; kill -s INT "$$"; exit'
0
kill
SIGINTハンドラを呼び出す前に、bashが最後に実行したコマンドであるコマンドの終了ステータスを取得できます。
$ bash -c 'trap "echo \$?" INT; (trap "" INT; sleep 3; exit 123); exit'
^C123
sleep
SIGINTを無視すると、Ctrl+を押した後Cも実行中のサブシェルが返されるのを待つ必要があり、sleep
ハンドラはサブシェルの終了ステータス(123)を印刷します。
複数の信号に対して同じハンドラを取り付ける場合は、信号をハンドラに渡すことができます。
handler() {
local signal="$1"
echo "I got $signal signal"
}
for signal in INT HUP TERM QUIT; do
trap "handler $signal" "$signal"
done
ところで、あなたは見つけることができます:
bash -c '(trap "" INT; sleep 3; exit 123); exit'
Ctrl+ で中断しようとしてもc終了状態 123 で終了しますが、これは実際に bash の設計です。詳しくは以下をご覧ください。ターミナルにctrl-cを入力したときにフォアグラウンドジョブが完了する前に終了しないのはなぜですか?