2009-10-29 11 views
13

を殺されたときにコマンドを実行している終了し、私はこのシェルスクリプトはbashを終了します対話型端末、Ctrl + Cからこれを実行するシェルスクリプトは、テストの目的のために

#!/bin/bash 
echo $$ 
find/>/dev/null 2>&1 

、およびfindコマンドを持っています。

$ ./test-k.sh 
13227 
<Ctrl+C> 
$ ps -ef |grep find 
$ 

バックグラウンドで実行すると、シェルを強制終了すると、スクリプトで実行中のコマンドが孤立します。

$ ./test-k.sh & 
[1] 13231 
13231 
$ kill 13231 
$ ps -ef |grep find 
nos 13232  1 3 17:09 pts/5 00:00:00 find/
$ 

このシェルスクリプトは、呼び出された方法に関係なく、終了時にすべての子プロセスを終了します。最終的にはPythonとJavaアプリケーションから開始されます。スクリプトが終了するとクリーンアップのいくつかの形式が必要になります。私が調べなければならないオプションや終了時に自身をクリーンアップするスクリプトを書き直す方法はありますか?

答えて

15

を殺すにシェルを模倣する方法を示していた私は考え

#!/bin/bash 
trap : SIGTERM SIGINT 

echo $$ 

find/>/dev/null 2>&1 & 
FIND_PID=$! 

wait $FIND_PID 

if [[ $? -gt 128 ]] 
then 
    kill $FIND_PID 
fi 

いくつかの説明は順調です。ゲートから、デフォルトの信号処理を変更する必要があります。 :はノーオペレーションコマンドです。空の文字列を渡すと、シェルは何かをするのではなくシグナルを無視します(これとは逆です)。

次に、findコマンドはバックグラウンドで(スクリプトの観点から)実行され、waitという組み込み関数が組み込まれて終了します。上記のtrapに実際のコマンドを与えたので、信号が処理されると、waitは128より大きいステータスで終了します。waitが完了すると、waitはそのプロセスの終了ステータスを返します。

最後に、waitがエラーステータスを返す場合は、killの子プロセスが必要です。幸運なことに私たちはPIDを保存しました。この方法の利点は、何らかのエラーメッセージを記録したり、信号によってスクリプトが終了したことを識別できることです。

他にも言及したように、出口の後ろに情報を残したくない場合は、trapに引数としてkill -- -$$を入力することは別のオプションです。

trapについてあなたが望むように動作するように、あなたはwaitでそれをペアリングする必要があるのですが - bashが完了し、trapが設定されている信号を受信するためのコマンドを待っている場合bash manページには、」言い、 trapはコマンドが完了するまで実行されません。 waitはこのやっかいを回避する方法です。

必要に応じて、より多くの子プロセスに拡張することもできます。私は実際にこれを徹底的にテストしたわけではありませんが、ここでうまくいくようです。

$ ./test-k.sh & 
[1] 12810 
12810 
$ kill 12810 
$ ps -ef | grep find 
$ 
+1

従来のno-opコマンドは "': '"です。 – ephemient

+0

ホット。今すぐ変更する。 –

+0

プロセスをバックグラウンドで起動すると、そのプロセスは強制終了されません。バックグラウンドで起動しないと、子プロセスが殺される –

0

あなたがする必要があることは、killシグナルをトラップし、findコマンドをkillして終了することです。

+3

'kill 'はデフォルトで' SIGTERM'を送ります。 'SIGKILL'は捕まえられない。 –

1

ちょうどあなたのスクリプトに次のような行を追加します。

trap "kill $$" SIGINT 

ときあなたはあなたのセットアップで「INT」に「SIGINT」に変更する必要があるかもしれませんが、これは基本的にあなたのプロセスを強制終了し、すべての子プロセスCtrl + Cを押します。

+2

の代わりに、 'kill $$'の代わりにfindコマンドのpidにTERMを送るべきでしょう! –

+1

'$!'おそらく、あなたはそれより細かい制御が必要でしょう。 – ephemient

6

グループに信号を送信します。 ので、代わりのkill 13231行います

kill -- -13231 

をあなたのpythonから開始している場合は、その後で見て: http://www.pixelbeat.org/libs/subProcess.py を開始し、グループ

+0

このスクリプトのすべてのコマンドは、そのプロセスグループに属しますか? – nos

+0

シェルから起動した場合、そうでない場合は、subProcess.pyで実行する必要があります – pixelbeat

+0

スクリプトの終了方法を常に制御するとは限りません – ndemou

7

この問題に対する洗練された解決策を探していて、次の解決策が他のところで見つかりました。

trap 'kill -HUP 0' EXIT 

私自身のmanページが何0手段については何も言ってませんが、周り掘ってから、現在のプロセスグループを意味するようです。スクリプトは自分自身のプロセスグループであるため、これはSIGHUPをすべてのスクリプトの子、フォアグラウンド、およびバックグラウンドに送信します。パトリックの答え@

+0

これはうまく動作するようです(ctrl-Cでスクリプトを強制終了して端末を閉じることによって試しました)が、私は隠された欠点を恐れています。彼の意見を共有したいと思うどんなbashの達人? – ndemou

+0

http://stackoverflow.com/a/22644006/301717同様の回答を示唆していますが、より堅牢なようです – Jezz

1

はほとんどのトリックをしましたが、あなたの現在シェルのプロセスが同じグループ(それはあまりにも親を殺す)である場合、それは動作しません。

私はこれが良いことが判明:

trap 'pkill -P $$' EXIT

参照here詳細は。

関連する問題