
自分が何を間違っているのか、そしてなぜ間違っているのかを理解しようと一生懸命努力しています。
launch.sh
を起動するスクリプトがありますprocess.sh
。
起動.sh
#!/bin/bash
while true; do
./process.sh
done
プロセス.sh
#!/bin/bash
function signalHandler() {
for i in {1..2}; do
sleep 0.1s
echo "process.sh: cleanup $i"
done
exit 130
}
trap "signalHandler" "SIGINT"
while true; do
sleep 1s
done
走るとき
./launch.sh &
そしてそれを殺す
kill -s SIGINT -$!
ここで、$!
最後のコマンド (launch.sh) の PID を取得し、マイナス記号ですべての子に信号を送信してからlaunch.sh
続行します。なぜでしょうか?
私は次のような動作を期待していました(このブログによるとシグナルとバッシュ) :
バックグラウンドでスクリプトを実行しているシェル Alaunch.sh
が中断され、Bash はprocess.sh
が終了するまで待機します。process.sh
のシグナル ハンドラにより が異常終了 (終了 130) を返すためprocess.sh
、シェル A は終了するはずです。なぜ終了しないのでしょうか。
この子のステータスが、そのシグナルが原因で異常終了したことを示している場合、シェルはクリーンアップし、シグナル ハンドラーを削除し、OS のデフォルト アクション (異常終了) をトリガーするために再度自身を強制終了します。または、trap で設定されたスクリプトのシグナル ハンドラーを実行して、続行します。
答え1
まず、exit 130
これは異常終了ではありません。これは正常終了であり、終了ステータスは130です。man 3 wait
(POSIX):
If the information pointed to by stat_loc was stored by a call to
waitpid() that specified the WUNTRACED and WCONTINUED flags,
exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
WIFSTOPPED(*stat_loc), and WIFCONTINUED(*stat_loc) shall evaluate to
a non-zero value.
WIFEXITED
は正常終了をチェックし、 はWIFSIGNALLED
キャッチされないシグナルによる終了です。これらは相互に排他的であるため、 はexit 130
正常です。
プロセスが SIGINT によって終了したときに終了ステータスが 130 になるのは、bash が SIGINT による終了を検出したため、プロセス外で終了ステータスを 130 に設定するためです。bash が Ctrl-C または Ctrl-Z で $? (終了ステータス) をゼロ以外に設定するのはなぜですか?
第二に、SIGINTを処理して終了するプロセスは、SIGINTで自分自身を終了させる必要があります。Gregのwiki(シェル関連の優れたリソース)には、これについてのメモ:
SIGINTのハンドラを設定する場合(EXITトラップを使用するのではなく)、SIGINTに応答して終了するプロセスはSIGINTで自分自身を殺す呼び出し元に問題が起こらないように、単に終了するのではなく、次のようになります。
trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
ここで、をexit 130
次のように変更したとします。
trap - INT
kill -INT $$
予想通りの動作が見られます。