2012-08-02 6 views
5

私はstdoutにテキストの行を単に出力する単純なPerlスクリプトを持っています。私が達成したいことは、このスクリプトが実行されている間に、私(または他の誰か)がそのプロセスに停止するシグナルを発行すると、そのシグナルをトラップして正常に終了させたいということです。私は実際には、コマンドラインからCtrl + Cキーを打ったとき、私はそれがちょうど死ぬPerlで信号をきれいにトラップする

kill -9 <pid> 

を発行した場合、これは、うまく動作しますが、私が持っているコードは、次の

#!/usr/bin/perl -w 

$| = 1; 
use sigtrap 'handler' => \&sigtrap, 'HUP', 'INT','ABRT','QUIT','TERM'; 
while(1){ 
print "Working...\n"; 
sleep(2); 
} 
sub sigtrap(){ 
print "Caught a signal\n"; 
exit(1); 
} 

のように見えます。終了する前に何かを実行するにはどうすればよいですか?私の一般的な考え方は、このフレームワークを使用して、メンテナンスや障害のためにサーバーが再起動されたために、このスクリプトがサーバー上で終了したときをキャプチャすることです。

ありがとうございます。

答えて

11

信号#9(SIGKILL)はトラップできません。これがUnixの設計方法です。

しかし、メンテナンスのためにシャットダウンすると、システムはその信号を送信しません。少なくともデーモンが正しく動作するかどうか。通常、TERMシグナル(またはより正確には、/etc/init.dのデーモン処理スクリプトが何をするか)を送信します。タイムアウト後に正しくシャットダウンしないプロセスだけがSIGKILLを受け取ります。

TERM信号を正しく処理し、システムがランレベルを変更しているときに呼び出される/etc/init.dにラッパースクリプトを書き込むことが目的です。

アップデート:Daemon::Controlモジュールをinitスクリプト用に使用できます。

4

あなたのプロセスには2つの異なるシグナルが送信されています。コンソールでCtrl-Cを押すと、通常、あなたのコードで判断したシグナルが捕捉されて修理され、 TERM INTのシグナルが送信されます。しかしkill -9は明示的に信号番号9を送ります。これはKILLと呼ばれます。これはサービスの再定義が不可能なシグナルの1つであり、このシグナルの送信は常にプロセスを直ちに終了させます。これはカーネル自体によって行われます。

+3

'Ctrl-C'を押すと、インタラクティブプロセスの場合はデフォルトアクションですが、' INT'シグナル**は 'TERM'ではなく**送信されます。 'kill -9'とは異なり、どちらのシグナルも捕まえることができます。 'kill -l'はシグナル名をリストします。 'stty -a'は' INT'の 'Ctrl-C'へのデフォルトマッピングを表示します。 – JRFerguson

+0

よろしく!それをクリアして誤解を招いて申し訳ありません。 –

3

私が知る限り、kill -9をキャプチャすることはできません。代わりにkill <pid>を試してください。

+2

これは 'TERM'を出力します。これは実質的にコンソールで' Ctrl-C'を押すのと同じです。 –

+0

@DanielKamilKozarありがとう、よく知っておいてください。 –

+3

@DanielKamilKozar: 'Ctrl-C'を押すと、インタラクティブプロセスの場合はデフォルトアクションですが、' INT'シグナル**が 'TERM'ではなく**送信されます。 'kill -9'とは異なり、どちらのシグナルも捕まえることができます。 'kill -l'はシグナル名をリストします。 'stty -a'は' INT'の 'Ctrl-C'へのデフォルトマッピングを表示します。 – JRFerguson

関連する問題