在perl中,当使用open创建子项时杀死孩子及其子女

前端之家收集整理的这篇文章主要介绍了在perl中,当使用open创建子项时杀死孩子及其子女前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是我的代码,为了清楚起见,删除错误处理和其他内容
sub launch_and_monitor {  

    my ($script,$timeout) = @_;

    sub REAPER {
        while ((my $child = waitpid(-1,&WNOHANG)) > 0) {}
        $SIG{CHLD} = \&REAPER;
    }
    $SIG{CHLD} = \&REAPER;

    my $pid = fork;
    if (defined $pid) {
        if ($pid == 0) {
            # in child
            monitor($timeout);
        }
        else {
            launch($script);
        }
    }
}

launch子程序执行一个shell脚本,然后启动其他进程,如下所示:

sub launch($) {

    my ($script) = @_;

    my $pid = open(PIPE,"$script|");

    # write pid to pidfile

    if ($pid != 0) {
        while(<PIPE>) {
            # do stuff with output
        }
        close(PIPE) or die $!;
    }
}

monitor sub基本上只等待一段指定的时间,然后尝试终止shell脚本.

sub monitor($) {

    my ($timeout) = @_;

    sleep $timeout;

    # check if script is still running and if so get pid from pidfile
    if (...) {
        my $pid = getpid(...);        
        kill 9,$pid;
    }
}

这会杀死脚本,但是它不会杀死任何子进程.怎么修?

解决方法

如果操作系统支持,则可以使用进程组执行此操作.您需要使脚本流程成为流程组负责人.它运行的子进程将从其父进程继承进程组.然后,您可以使用kill同时向组中的每个进程发送信号.

在launch()中,您需要将打开的行替换为fork.然后在子进程中,在执行命令之前调用setpgrp().像下面这样的东西应该工作:

my $pid = open(PIPE,"-|");
if (0 == $pid) {
    setpgrp(0,0);
    exec $script;
    die "exec Failed: $!\n";
}
else {
    while(<PIPE>) {
        # do stuff with output
    }
    close(PIPE) or die $!;
}

稍后,为了终止脚本进程及其子进程,否定您发出的进程ID:

kill 9,-$pid;

猜你在找的Perl相关文章