SIGTERM bash トラップ失敗

SIGTERM bash トラップ失敗

信号をキャプチャする非常に簡単なスクリプトがあります。

#!/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プログラムであることを覚えておいてください。スクリプトがトラップを設定しなくても、シグナルのハンドラを設定できます。

両方のトラップラインはコメントアウトされています。
SIGTERMSent: 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他の端末ウィンドウのメッセージは無視されます!

同じ上記と。

おすすめ記事