信号をキャプチャする非常に簡単なスクリプトがあります。
#!/bin/bash
unlink SigTermRecieved
unlink SigIntRecieved
#trap " touch SigTermRecieved ; exit " SIGTERM
trap " touch SigIntRecieved ; exit " SIGINT
echo "pid is $$"
while true
do
sleep 60m
done
exit
行動
両方のトラップラインはコメントアウトされます:
SIGTERM Sent:Terminate program。
?別のターミナルウィンドウから送信されたSIGINTは無視されました!
CTRL Cはプログラムを終了します。
SIGTERM トラップはコメントアウトされません。
? SIGTERM送信済み:プログラムは終了せず、SIGTERMトラップは実行されません。
?別のターミナルウィンドウから送信されたSIGINTは無視されました!
CTRL Cはプログラムを終了します。
コメントアウトされていないSIGINTトラップ:
SIGTERM送信済み:プログラムを終了します。
?他の端末ウィンドウのSIGINTが無視されました!
CTRL C はトラップコードを実行し、プログラムを終了します。
以前の行動?予期しないこと、または間違ったことです。私はSIGINTの動作にあまり興味がありません。私はトラップの1つが動作していることを確認するためにこれを試しました。
だからスヌーズ機能を削除し、次のようにしました。
sleep 60m &
wait $!
次にkill -TERM -pid
、両方のプロセスを終了し、SIGTERM トラップを実行します。
私のアプリケーションでは、いくつかの詳細をクリーンアップできるように、システムがシャットダウンしたときにSIGTERMを待っています。シャットダウンが使用されたかpid
どうかは不明です-pid
。どちらも私にとって効果的であり、システムは最終的にすべてのプロセスを終了します。テスト中にいくつかの吊り下げられた睡眠プロセスは大きな問題ではありませんでした。
fifoのソリューションは非常に複雑で理解できません。
助けてくれてありがとう。
ベストアンサー1
[以下の説明bash
(または他のシェル)はCプログラムであることを覚えておいてください。スクリプトがトラップを設定しなくても、シグナルのハンドラを設定できます。
両方のトラップラインはコメントアウトされています。
SIGTERM
Sent: Terminate Program。
bash
ハンドラが設定されていないため、SIGTERM
この信号はそれを完全に終了し、それを開始したシェルがプロンプトに戻ります。ただし、sleep
外部プログラムであり、別のサブプロセスで実行されるコマンドは、(pgrep -a sleep
確認のために)実行され続けます。
?
SIGINT
他の端末ウィンドウから送信されたメッセージは無視されます!
sleep
この場合のように、子プロセスを待つときbash
にシグナルハンドラを設定し、トラップがSIGINT
設定されていない場合はそのシグナルを無視します。ただし、同じ信号によって待機しているサブプロセスが終了する場合は除外されます。 。bash
信号によって終了されたか、どの信号かを子の終了状態から収集できます。
これを「待って協力していく」といいます(世界教育協議会SIGINT
)と信号にのみ適用されますSIGQUIT
。
SIGINT
他のシェルはこれを行わない可能性があり、待機しているサブプロセスが終了するまでシグナルに対するアクションを遅らせることができます。合計bash
比較の例dash
:
$ ( (sleep .2; pkill -INT -P $$)&); dash -c 'while :; do /bin/sleep 3; done'
<dash is killed by a self-raised SIGINT after 3 seconds>
$ ( (sleep .2; pkill -INT -P $$)&); bash -c 'while :; do /bin/sleep 3; done'
^C
<bash has to be killed by hand with Control-C>
CTRL C
プログラムを終了します。
AはCtrl-C
原因になりますコアSIGINT
シグナルを送信みんなフォアグラウンドプロセスグループ(作業)のプロセス。この場合、以下が含まれます。両方あなたのスクリプトとsleep
その添え字。kill
次のコマンドを使用してこれをシミュレートできます。否定的なPIDプロセスチーム長(プロセスグループIDと同じ)またはkill
ジョブIDと一緒に組み込みシェルを使用します。
bash -c 'sleep 3600; echo DONE' &
[1] 12381
kill -INT -12381 # or kill -INT %1
スクリプトの負の pid は、次の場合にのみ使用してください。プロセスチーム長。スクリプトがサブシェルまたは他のスクリプトから呼び出された場合、またはパイプラインの一部として呼び出される場合は、そうでない可能性があります。
トラップは
SIGTERM
コメントアウトされません。
?SIGTERM
送信済み:プログラムが終了せず、SIGTERM
トラップが実行されませんでした。
はい、トラップが実行されます。ただし、sleep
注文が終了した後にのみ可能です。確認のために60分を待たない場合は、sleep 1
代わりに使用してください;-)sleep 60m
これはリンクされた答えでも説明されています。ここでは標準要件アクション。
トラップはコメントアウトされ
SIGINT
ませんでした。
?SIGINT
他の端末ウィンドウのメッセージは無視されます!
同じ上記と。