6

我在 perl 中创建了一个脚本来运行超时的程序。如果正在执行的程序花费的时间比超时时间长,则脚本会终止该程序并返回消息“TIMEOUT”。

该脚本运行良好,直到我决定重定向已执行程序的输出。

当 stdout 和 stderr 被重定向时,脚本执行的程序不会被杀死,因为它的 pid 与我从 fork 得到的不同。

在重定向的情况下,似乎 perl 执行了一个执行我的程序的 shell。

我想要输出重定向,但在超时的情况下仍然能够终止程序。

关于我如何做到这一点的任何想法?

我的脚本的简化代码是:

#!/usr/bin/perl

use strict;
use warnings;
use POSIX ":sys_wait_h";

my $timeout = 5;
my $cmd = "very_long_program 1>&2 > out.txt";

my $pid = fork();
if( $pid == 0 )
{
   exec($cmd) or print STDERR "Couldn't exec '$cmd': $!";
   exit(2);
}
my $time = 0;
my $kid = waitpid($pid, WNOHANG);
while ( $kid == 0 )
{
   sleep(1);
   $time ++;
   $kid = waitpid($pid, WNOHANG);
   print "Waited $time sec, result $kid\n";
   if ($timeout > 0 && $time > $timeout)
   {
      print "TIMEOUT!\n";
      #Kill process
      kill 9, $pid;
      exit(3);
   }
}

if ( $kid == -1)
{
   print "Process did not exist\n";
   exit(4);
}
print "Process exited with return code $?\n";
exit($?);

谢谢你的帮助。

4

2 回答 2

12

尝试$cmd

my $cmd = "very_long_program 1>&2 > out.txt";

my $cmd = "exec very_long_program 1>&2 > out.txt";

exec告诉由 perl 生成的 shell 用very_long_program 替换自己,而不是像孩子一样运行very_long_program。

(在这种情况下,perl 产生一个 shell 的原因是因为$cmd包含重定向字符 - 而 perl 不知道如何自己处理它们。解决问题的另一种方法是在fork()调用之后但之前在 perl 本身中进行重定向exec()- 但这有点棘手,所以exec先尝试解决方法!)

于 2010-06-03T10:36:24.657 回答
2

另一种方法是在 fork 之后重定向 STDOUT 和 STDERR 并在没有重定向的情况下运行命令:

open(STDOUT, ">", "out.txt") or die "Err: $!";
open(STDERR, ">&STDOUT");
exec("very_long_command");
die "Failed to exec very_long_command: $!";
于 2010-06-03T15:11:25.430 回答