Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 处理挂起进程的输出_Perl - Fatal编程技术网

Perl 处理挂起进程的输出

Perl 处理挂起进程的输出,perl,Perl,我想用perl脚本运行一些测试可执行文件,解析它们的STDOUT,并根据STDOUT包含的内容返回一个exit值。我对perl不是很熟悉,所以有点难 我遇到的问题是,即使测试可执行文件崩溃或挂起,也要确保我的perl脚本能够接收任何输出 目前,我正在使用闹钟超时。如果它挂起,我只想获取我能获取的任何数据并继续解析。不幸的是,使用我当前的执行方法,如果它挂起,我将无法获得任何数据,僵尸进程将永远存在 我(可能是天真的)获取测试输出的版本也是如此 #!/usr/bin/perl use strict

我想用perl脚本运行一些测试可执行文件,解析它们的STDOUT,并根据STDOUT包含的内容返回一个exit值。我对perl不是很熟悉,所以有点难

我遇到的问题是,即使测试可执行文件崩溃或挂起,也要确保我的perl脚本能够接收任何输出

目前,我正在使用闹钟超时。如果它挂起,我只想获取我能获取的任何数据并继续解析。不幸的是,使用我当前的执行方法,如果它挂起,我将无法获得任何数据,僵尸进程将永远存在

我(可能是天真的)获取测试输出的版本也是如此

#!/usr/bin/perl
use strict;
use warnings;

my @output;

eval {
   local $SIG{ALRM} = sub {die "alarm\n"};
   alarm 15;
   @output = `testExecutable`;
   alarm 0;
};

if ($@) {
  die unless $@ eq "alarm\n";
  print "timed out\n";
}
else {
  print "didn't time out\n";
}

print @output;
基本上,我需要以一种方式执行testExecutable,这种方式允许我在警报响起之前访问它输出的任何数据,然后在警报处理程序中终止testExecutable进程


如果需要,我可以修改测试可执行文件。环顾四周,缓冲似乎是一个值得关注的问题。

您的问题是,使用backquote操作符只能在完成时填充perl变量。因此,您应该从perl管道中读取。比如说:

#!/usr/bin/env perl
use strict;
use warnings;

my @output;

eval {
    local $SIG{ALRM} = sub {die "alarm\n"};
    alarm 15;
    open my $pipe_handle, '-|', 'testExecutable' or die "open error: $!";
    while (my $line = <$pipe_handle>) {
        push @output, $line;
    }
    close $pipe_handle;
    alarm 0;
};

if ($?) {
    print "testProgram failed\n";
} elsif ($@) {
    die unless $@ eq "alarm\n";
    print "timed out\n";
} else {
    print "didn't time out\n";
}

print @output;
#/usr/bin/env perl
严格使用;
使用警告;
我的@output;
评估{
本地$SIG{ALRM}=sub{die“alarm\n”};
警报15;
打开我的$pipe_句柄、'-|'、'testExecutable'或死“open error:$!”;
while(我的$line=){
按@输出,$line;
}
关闭$pipe_手柄;
报警0;
};
如果($?){
打印“测试程序失败\n”;
}elsif($@){
除非$@eq“报警\n”,否则将导致死亡;
打印“超时\n”;
}否则{
打印“未超时\n”;
}
打印@输出;
请记住,可能有一些缓冲正在进行,因此您仍然可能会错过一些输出


编辑:在检查
$?
中添加,以检查子程序的状态

将外部命令的输出写入文件,并在过程完成时读取文件(正常或超时)。正如索德维德所说,最好是让外部程序频繁刷新其输出

my $output_file = '/tmp/foo';
eval {
   local $SIG{ALRM} = sub {die "alarm\n"};
   alarm 15;
   system("testExecutable > $output_file 2>&1");
   alarm 0;
};

# whether successful or not, there could be output in $output_file ...
open my $fh, '<', $output_file;
@output = <$fh>;
close $fh;
unlink $output_file;
my$output_file='/tmp/foo';
评估{
本地$SIG{ALRM}=sub{die“alarm\n”};
警报15;
系统(“testExecutable>$output_file 2>&1”);
报警0;
};
#无论成功与否,$output\u文件中都可能有输出。。。

打开我的$fh,'我以前实际上有差不多的代码,但它似乎没有很好地发挥报警信号。与backticks不同的是,在我杀死脚本之前,它不会打印它超时,而且我仍然没有输出。也就是说,它与您的代码不是100%完全相同,所以我会尽快尝试。而且,这并不能解决终止挂起的测试进程的问题。不过,还是要谢谢你的帮助。@Slavik81抱歉,错过了。将它添加到中,检查$?打开的管道返回子项的pid,您可以使用它在超时时终止它。您可能希望在循环中添加另一个
报警15
,以便在看到一些输出时重置超时。这几乎可以正常工作。但是,我仍然保留while循环的条件。前一行执行得很好,但while循环的主体永远不会执行,而且警报无法使我脱离挂起状态。^C允许脚本继续执行,但从不填充@output。这实际上会将我的输出发送到一个文件,并在超时时正确中止,所以这很好。但是,我仍然需要该测试可执行文件的pid,以便在它挂起时终止它。可能还有脚本本身的pid,这样我就可以生成一个唯一的输出文件名。