在perl中重定向输出时fork exec kill出现问题

在perl中重定向输出时fork exec kill出现问题,perl,redirect,fork,kill,Perl,Redirect,Fork,Kill,我用perl创建了一个脚本来运行超时的程序。如果正在执行的程序比超时时间长,则脚本将终止该程序并返回消息“timeout” 在我决定重定向已执行程序的输出之前,脚本运行得相当好 当stdout和stderr被重定向时,脚本执行的程序不会被终止,因为它的pid与我从fork获得的pid不同 perl似乎执行一个shell,在重定向的情况下执行我的程序 我希望有输出重定向,但仍然能够在超时的情况下杀死程序 有什么办法可以做到吗 我的脚本的简化代码是: #!/usr/bin/perl use str

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

在我决定重定向已执行程序的输出之前,脚本运行得相当好

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

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($?);

谢谢您的帮助。

尝试从更改
$cmd

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

exec
将告诉由perl生成的shell用非常长的程序替换自己,而不是作为子程序运行非常长的程序


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

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

open(STDOUT, ">", "out.txt") or die "Err: $!";
open(STDERR, ">&STDOUT");
exec("very_long_command");
die "Failed to exec very_long_command: $!";
open(STDOUT, ">", "out.txt") or die "Err: $!";
open(STDERR, ">&STDOUT");
exec("very_long_command");
die "Failed to exec very_long_command: $!";