5

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

#!/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>

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

非常感谢提前

4

3 回答 3

11

信号#9 (SIGKILL) 不能被捕获。这就是 Unix 的设计方式。

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

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

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

于 2012-08-02T22:11:57.400 回答
4

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

于 2012-08-02T21:51:17.753 回答
3

据我所知,您无法捕获kill -9。试试kill <pid>吧。

于 2012-08-02T22:02:14.030 回答