【问题标题】:Trapping signals cleanly in Perl在 Perl 中干净地捕获信号
【发布时间】:2012-07-31 22:42:18
【问题描述】:

我有一个简单的 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>

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

非常感谢

【问题讨论】:

    标签: perl unix signals daemon


    【解决方案1】:

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

    【讨论】:

    • 按下Ctrl-C 会发送INT 信号not TERM,尽管默认操作与交互过程相同。与kill -9 不同,任何一个信号都可以被捕获。 kill -l 将列出信号名称。 stty -a 将显示 INTCtrl-C 的默认映射。
    • 哎哟!感谢您清除它,并抱歉误导。
    【解决方案2】:

    据我所知,您无法捕获kill -9。请改用kill &lt;pid&gt;

    【讨论】:

    • 这将传递一个TERM,实际上相当于在控制台中按Ctrl-C
    • @DanielKamilKozar :按下Ctrl-C 会发送INT 信号not TERM,尽管对于交互过程来说默认操作相同。与kill -9 不同,任何一个信号都可以被捕获。 kill -l 将列出信号名称。 stty -a 将显示 INTCtrl-C 的默认映射。
    【解决方案3】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      相关资源
      最近更新 更多