2

我有一个使用 OPEN 和管道执行的命令,我想设置 10 秒的超时时间,如果执行时间超过此时间,则子进程中止。但是,我的代码只会导致程序挂起 - 为什么我的 ALARM 没有正确传递?

my $pid = 0;
my $cmd = "someCommand";
print "Running Command # $num";
eval {
    local $SIG{ALRM} = sub {                    
        print "alarm \n";
        kill 9, $pid;
    };              
    alarm 10;
    pid = open(my $fh, "$cmd|");
    alarm 0;
};
if($@) {
    die unless $@ eq "alarm \n";
} else {
    print $_ while(<$fh>);
}

编辑:

所以从下面的答案中,这就是我所拥有的:

my $pid = open(my $fh, qq(perl -e 'alarm 10; exec \@ARGV; die "exec: $!\n" ' $cmd |));
print $_ while(<$fh>);

但是当警报超时时,这个打印 ALARM CLOCK 到控制台......而我没有在代码中的任何地方指定这个......我怎样才能摆脱这个,我应该把自定义警报事件处理程序放在哪里?

谢谢!

4

2 回答 2

3

我想设置 10 秒的超时时间,如果执行时间超过这个时间,子进程会中止

另一种方法是在子进程本身上设置警报,使用您已经拥有的方便的脚本语言:

my $cmd = "someCommand";
my $pid = open(my $child_stdout, '-|',
   'perl', '-e', 'alarm 10; exec @ARGV; die "exec: $!"', $cmd);
...

您的子进程最初将是 perl(好吧,shell 然后是 perl),它将对其自身设置警报,然后 exec(将自身替换为)$someCommand。但是,挂起的警报会跨s继承exec()

于 2013-08-19T17:21:28.123 回答
2

您的代码所做的只是在open调用上设置 10 秒超时,而不是在整个外部程序上。您希望将与外部命令的其余交互带入eval块中:

eval {
    local $SIG{ALRM} = sub {                    
        print "alarm \n";
        kill 9, $pid;
    };              
    alarm 10;
    $pid = open(my $fh, "$cmd|");
    print while <$fh>;
    close $fh;
    alarm 0;
};
if($@) {
    die unless $@ eq "alarm \n";
}
于 2013-08-19T18:56:40.693 回答