我写Perl脚本,这将编写一些投入和那些投入外部程序。有一个小而非零的机会,这一计划将挂,我想要时间,它:

my $pid = fork;
if ($pid > 0){
    eval{
        local $SIG{ALRM} = sub { die "TIMEOUT!"};
        alarm $num_secs_to_timeout;
        waitpid($pid, 0);
        alarm 0;
    };
}
elsif ($pid == 0){
    exec('echo blahblah | program_of_interest');
    exit(0);
}

因为它的立场,现在,美元后num_secs_to_timeout,program_of_interest仍然存在。我想杀了它在匿名的子程序 $SIG{ALRM} 如下:

local $SIG{ALRM} = sub{kill 9, $pid; die "TIMEOUT!"}

但是,这并不做任何事情。program_of_interest仍然坚持。我怎么去杀这一进程?

有帮助吗?

解决方案

我能够成功地杀死我的exec()ed过程 杀人的过程组, ,如问题的回答 在perl,杀害儿童和儿童当儿童创建了使用开放.我修改我的代码如下:

my $pid = fork;
if ($pid > 0){
    eval{
        local $SIG{ALRM} = sub {kill 9, -$PID; die "TIMEOUT!"};
        alarm $num_secs_to_timeout;
        waitpid($pid, 0);
        alarm 0;
    };
}
elsif ($pid == 0){
    setpgrp(0,0);
    exec('echo blahblah | program_of_interest');
    exit(0);
}

后超时,program_of_interest是成功地杀死。

其他提示

在上面的代码(由strictlyrude27)没有工作开箱,因为 - $ PID的是大写字母拼写。 (顺便说一句:还有还有: http://www.gnu.org /software/coreutils/manual/html_node/timeout-invocation.html

下面是与测试的示例:

#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;

my $prg = basename $0;
my $num_secs_sleep = 2;
my $num_secs_to_timeout = 1;
my $orig_program = "sleep $num_secs_sleep; echo \"Look ma, survived!\"";
my $program = $orig_program;
my $expect = "";

if (@ARGV){
  if($ARGV[0] eq "test"){
    test();
    exit 0;
  } elsif (@ARGV == 1) {
    $num_secs_to_timeout = $ARGV[0];
  } elsif (@ARGV == 2) {
    $program = $ARGV[0];
    $num_secs_to_timeout = $ARGV[1];
  } else {
    die "Usage: $prg [ \"test\" | [program] seconds ] "
  }
}

if($orig_program eq $program) {
  if(@ARGV < 2) {
    $expect = $num_secs_to_timeout > $num_secs_sleep ?
      "(we expected to survive.)" : "(we expected to TIME OUT!)";
  }
  print STDERR "sleeping: $num_secs_sleep seconds$/";
}

print STDERR <<END;
  timeout after: $num_secs_to_timeout seconds,
  running program: '$program'
END

if($orig_program eq $program) {
  print STDERR "$expect$/";
}

exit Timed::timed($program, $num_secs_to_timeout);

sub test {
  eval "use Test::More qw(no_plan);";
  my $stdout;
  close STDOUT;
  open STDOUT, '>', \$stdout or die "Can't open STDOUT: $!";
  Timed::timed("sleep 1", 3);
  is($stdout, undef);
  Timed::timed("sleep 2", 1);
  is($stdout, "TIME OUT!$/");
}

################################################################################
package Timed;
use strict;
use warnings;

sub timed {
  my $retval;
  my ($program, $num_secs_to_timeout) = @_;
  my $pid = fork;
  if ($pid > 0){ # parent process
    eval{
      local $SIG{ALRM} = 
        sub {kill 9, -$pid; print STDOUT "TIME OUT!$/"; $retval = 124;};
      alarm $num_secs_to_timeout;
      waitpid($pid, 0);
      alarm 0;
    };
    return defined($retval) ? $retval : $?>>8;
  }
  elsif ($pid == 0){ # child process
    setpgrp(0,0);
    exec($program);
  } else { # forking not successful
  }
}

你的代码对我的作品, 经过一些微小的修改-我假设的变化作出自己的代码成一个通用的例子。

因此,让我用两个理念:

  1. 你删除的问题,当你创造了代码样本 -尝试建立一个小样本,实际上运行(我不得不改变'program_of_interest'and$num_secs_to_timeout到真正的价值,以测试它)。确保样本具有同样的问题。
  2. 这是什么做的program_of_interest你正在运行 -就我所知,你不能掩盖一个杀了9,但也许有一些事情。你有没有尝试测试你的代码一个非常简单的的剧本。我创建了一个为我的测试,去while(1){print"嗨 ";睡眠1;}
  3. 别的东西.

祝你好运...

的唯一方法SIGKILL可以忽略是,如果该过程停留在一个系统调用其是不间断。检查挂起的进程的状态(与ps aux)如果状态为d,则该过程不能被杀死。

您可能还需要检查函数被调用由它输出的东西。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top