Perl 脚本用于记录外部可执行文件输出和错误,同时仍在运行

标签 perl pipe stdout executable stderr

我有一个运行外部可执行文件的 Perl 脚本。该可执行文件运行一段时间(有时几秒钟,有时一小时),可以向 STDOUT 和 STDERR 输出文本以及退出代码,这些都是必需的。以下代码演示了第一个成功的外部可执行文件运行(带有一行的小 bash 脚本 - 注释),然后退出状态错误(gs - ghostscript 示例)。 我希望外部可执行文件将其 STDOUT 提供给 Perl 脚本以进行评估、过滤、格式化等,然后在外部文件仍在执行时将其记录到日志文件(也用于其他内容)。 STDERR 也很适合以同样的方式工作。 该脚本用于记录来自 STDOUT 的所有内容,但仅在可执行文件完成后。并且 STDERR 仅直接记录,没有评估等。我无法安装任何额外的 Perl 部件、模块等。

如何让我的 Perl 脚本在可执行文件吐出时(不仅仅是在最后)从可执行文件中获取每一行 (STDOUT + STDERR) 以及用于其他目的的退出代码?

#!/usr/bin/perl
@array_executable_and_parameters = "/home/username/perl/myexecutable.sh" ; #ls -lh ; for i in {1..5}; do echo X; sleep 1; done
@array_executable_and_parameters2= "gs aaa" ;
my $line;
chdir("/home/username/perl/");
$logFileName = "logfileforsomespecificinput.log";
open(LOGHANDLE, ">>$logFileName" );
open (STDERR, '>>', $logFileName);                  #Prints to logfile directly
#open (STDERR, '>>', <STDOUT>);                 #Prints to own STDOUT (screen or mailfile)

print LOGHANDLE "--------------OK run\n";
open CMD, '-|', @array_executable_and_parameters or die $@;
while (defined($line = <CMD>)) {                    #Logs all at once at end
    print LOGHANDLE "-----\$line=$line-----\n";
}
close CMD;
$returnCode1= $?>>8;
print LOGHANDLE "\$returnCode1=$returnCode1\n";

print LOGHANDLE "--------------BAD run\n";
open CMD2, '-|', @array_executable_and_parameters2 or die $@;
while (defined($line = <CMD2>)) {
    print LOGHANDLE "-----\$line=$line-----\n";
}
close CMD2;
$returnCode2= $?>>8;
print LOGHANDLE "\$returnCode2=$returnCode2\n";

close(LOGHANDLE);

Take 2. 在评论中提出好的建议后,我尝试了 IPC::Run。但是有些东西仍然没有按预期工作。我似乎不知道从开始(或泵?)到完成的循环是如何工作的,以及当我不知道最后的输出是什么时如何让它迭代——正如到处都提到的例子。到目前为止,我现在有以下代码,但它不能逐行工作。它一次性吐出文件列表,然后等到外部循环完全完成以打印所有 X。我如何驯服它以满足最初的需求?

#! /usr/bin/perl
use IPC::Run qw( start pump finish );

@array_executable_and_parameters = ();
push(@array_executable_and_parameters,"/home/username/perl/myexecutable.sh"); #ls -lh ; for i in {1..5}; do echo X; sleep 1; done
my $h = start \@array_executable_and_parameters, \undef, \$out, \$err ;
pump $h;# while ($out or $err);
print "1A. \$out: $out\n";
print "1A. \$err: $err\n";
$out = "";
$err = "";
finish $h or die "Command returned:\n\$?=$?\n\$@=$@\nKilled by=".( $? & 0x7F )."\nExit code=".( $? >> 8 )."\n" ;
print "1B. \$out: $out\n";
print "1B. \$err: $err\n";

最佳答案

IPC模块,尤其是 IPC::Cmd , IPC::Run如果不满意,那么 IPC::Run3 .您需要了解很多细节,而这些模块将使您的生活变得更加轻松。

关于Perl 脚本用于记录外部可执行文件输出和错误,同时仍在运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48187395/

相关文章:

perl - NCurses 和 Perl,任何指南?

node.js - Node 进程在 writeStream 结束前退出

c++ - 为什么 'dd' 从管道读取的速度比我自己使用 ifstream 的程序更快?

python - p.stdout.read() 在我的 Python 3 代码中不起作用

javascript - 网络爬虫 : Using Perl's MozRepl module to deal with Javascript

perl - -> 运算符在 Perl 中有什么作用?

perl - 保持特定位数的简单 Perl 数学

c - 从管道消费数据的最佳方式是什么?

python-3.x - 管道到ffmpeg时如何在python3中使用stdout.write?

python - 将所有 stdout/stderr 全局重定向到记录器