私は何が間違っているのか、そしてその理由が何であるかを理解しようとして本当に頑張っています。
launch.sh
起動スクリプトがありますprocess.sh
。
start.sh
#!/bin/bash
while true; do
./process.sh
done
process.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
します。なぜ?
次のような行動を楽しみにしています(このブログによると信号とスラム):
バックグラウンドでスクリプトを実行しているシェルAがlaunch.sh
ハングし、Bashがprocess.sh
完了するのを待ちます。process.sh
のシグナルハンドラが例外return(出口130)を発生させるため、process.sh
シェルAを終了する必要があります。なぜできないの?
子プロセスの状態がこのシグナルのために異常終了したことを示す場合、シェルはクリーンアップし、対応するシグナルハンドラを削除し、再びシャットダウンしてオペレーティングシステムのデフォルト動作(異常終了)をトリガーします。または、トラップ設定に従ってスクリプトのシグナルハンドラを実行し、続行します。
答え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
捕捉されていない信号により終了する。これらは相互に排他的であるため、anexit 130
は正常です。
SIGINTがプロセスを終了すると、bashはSIGINTが終了を検出し、プロセスの外部でこれを130に設定するため、終了ステータスは130です。bashが$を設定するのはなぜですか? (終了ステータス) が Ctrl-C または Ctrl-Z ではゼロではないのですか?
次に、SIGINTを処理してから終了するプロセスは、SIGINTを使用して自分で終了する必要があります。 Gregのwiki(シェルのための素晴らしい資料)これに関する注意:
EXITトラップを使用する代わりにSIGINTのハンドラを設定することを選択した場合、SIGINTに応答して終了するプロセスSIGINTで自殺発信者に問題を引き起こさないように、単に終了するだけではありません。したがって:
trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
さて、次のように変更した場合exit 130
:
trap - INT
kill -INT $$
予想される動作を確認できます。