在Perl中干净地捕获信号

时间:2012-08-02 21:47:58

标签: perl unix signals daemon

我有一个简单的Perl脚本,它只是将一行文本打印到stdout。我想要完成的是,当这个脚本运行时,如果我(或其他人)向该进程发出信号停止,我希望它捕获该信号并干净地退出。我的代码如下所示

#!/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);
}

虽然当我从命令行实际命中ctrl-c时这很有效,但是如果我发出

kill -9 <pid>

它就死了。如何让它在退出前执行某些操作?我的一般想法是使用此框架捕获此脚本在服务器上因服务器重新启动而导致维护或故障而死亡的时间。

非常感谢提前

3 个答案:

答案 0 :(得分:11)

信号#9(SIGKILL)无法被困。这就是Unix的设计方式。

但是在关闭维护时系统不发送该信号。至少你的守护进程是否正常运行。它通常会发送TERM信号(或者更确切地说是/etc/init.d中您的守护程序处理脚本所发生的信号)。只有在超时后未正确关闭的进程才会收到SIGKILL。

因此,您的目标应该是正确处理TERM信号并在/etc/init.d中编写包装脚本,该脚本将在系统更改运行级别时调用。

更新:您可以将Daemon::Control模块用于init脚本。

答案 1 :(得分:4)

您正向您的流程发送两个截然不同的信号。在控制台中按Ctrl-C通常会向进程发送 TERM INT信号,该信号 - 根据您的代码判断 - 被捕获并提供服务。但是,kill -9显式发送了第9号信号,称为KILL。这是其服务无法重新定义的信号之一,此信号的传递总是立即结束进程,这由内核本身完成。

答案 2 :(得分:3)

据我所知,你无法捕获kill -9。请改为kill <pid>