我想用perl脚本运行一些测试可执行文件,解析它们的STDOUT,并根据STDOUT包含的内容返回一个退出值。我对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进程。
如有必要,我可以修改测试可执行文件。环顾四周,似乎缓冲可能会引起一些担忧。
答案 0 :(得分:1)
问题在于,使用反引号运算符只会在完成时填充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;
请记住,可能会有一些缓冲区继续存在,所以你仍然可能错过了一些输出。
编辑:添加以检查$?
以检查子计划的状态
答案 1 :(得分:1)
将外部命令的输出写入文件,并在过程完成时读取文件(正常或超时)。就像Sodved说的那样,最好能让外部程序经常刷新输出。
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;