Perl IPC::Run 附加输出并解析标准错误,同时将其保存在一批文件中
Posted
技术标签:
【中文标题】Perl IPC::Run 附加输出并解析标准错误,同时将其保存在一批文件中【英文标题】:Perl IPC::Run appending output and parsing stderr while keeping it in a batch of files 【发布时间】:2011-06-21 14:23:26 【问题描述】:我正试图围绕 IPC::Run 进行以下操作。文件列表:
我的@list = ('/my/file1.gz','/my/file2.gz','/my/file3.gz');我想执行一个内置解压的程序,对它们进行一些编辑和过滤,然后打印到 stdout,给 stderr 一些统计信息:
~/myprogram 选项 $file我想将列表中所有文件的执行标准输出附加到一个 $out 文件中,并且能够在每个标准错误中解析和存储几行作为变量,同时让其余的被写出为每个输入文件分成单独的 fileN.log 文件。 我希望标准输出都进入“>>$all_into_one_single_out_file”,这是我想保留在不同日志中的错误。
阅读手册后,我已经走到了下面的代码,其中注释部分我不知道该怎么做:
@list 中的 $file 我的@cmd; push @cmd, "~/myprogram options $file"; IPC::运行::运行 \@cmd, \undef, ">>$out", 子 我的 $foo .= $_[0]; #检查我是否想保留我的线路,将值保存到 $mylog1 或 $mylog2 #let $foo 和所有其他行被写入 $file.log ;有什么想法吗?
【问题讨论】:
IPC::Run::run
的 @cmd
参数不是命令列表,它是单个命令的参数列表。如果要运行多个后台进程,请多次调用IPC::Run::run
。
@mob:啊,谢谢,我已经相应地改写了我的问题
【参考方案1】:
首先要做的事情。 my $foo .= $_[0]
不是必需的。 $foo
是一个新的(空)值,因此通过 .=
附加到它不会做任何事情。你真正想要的是一个简单的my ($foo) = @_;
。
接下来,您希望将每个命令的输出转到一个特定文件,同时(取决于某些条件)将相同的输出放到一个公共文件中。
Perl(在其他语言中)有一个很好的工具来帮助解决这样的问题,它被称为闭包。无论在子例程定义时哪些变量在范围内,这些变量都可供您使用。
use strict;
use warnings;
use IPC::Run qw(run new_chunker);
my @list = qw( /my/file1 /my/file2 /my/file3 );
open my $shared_fh, '>', '/my/all-stdout-goes-here' or die;
open my $log1_fh, '>', '/my/log1' or die "Cannot open /my/log1: $!\n";
open my $log2_fh, '>', '/my/log2' or die "Cannot open /my/log2: $!\n";
foreach my $file ( @list )
my @cmd = ( "~/myprogram", option1, option2, ..., $file );
open my $log_fh, '>', "$file.log"
or die "Cannot open $file.log: $!\n";
run \@cmd, '>', $shared_fh,
'2>', new_chunker, sub
# $out contains each line of stderr from the command
my ($out) = @_;
if ( $out =~ /something interesting/ )
print $log1_fh $out;
if ( $out =~ /something else interesting/ )
print $log2_fh $out;
print $log_fh $out;
return 1;
;
当不再被任何东西引用时,每个输出文件句柄都将被关闭——在这种情况下,在这个 sn-p 的末尾。
我修复了你的@cmd
,虽然我不知道你的option1
,option2
,...会是什么。
我还更改了您呼叫run
的方式。你可以用一个简单的>
来调用它,告诉它下一件事是输出,new_chunker
(来自 IPC::Run)会将你的输出分解为一次一行而不是全部一次性输出。
我还跳过了您正在输出到.gz
文件的事实。如果你想写入压缩文件,而不是打开为:
open my $fh, '>', $file or die "Cannot open $file: $!\n";
只要打开:
open my $fh, '|-', "gzip -c > $file" or die "Cannot startup gzip: $!\n";
这里要小心,因为这是命令注入的好地方(例如,让$file
成为/dev/null; /sbin/reboot
。如何处理这个问题在许多其他地方都给出了,超出了您实际询问的范围.
EDIT
: 重新阅读问题,并更改答案以更贴近实际问题。
EDIT2:
:根据您的评论更新。所有的标准输出都进入一个文件,命令中的标准错误被馈送到内联子例程。还修正了一个愚蠢的错字(因为语法是伪代码而不是 Perl)。
【讨论】:
hmmm,ifs 正在查看 stdout,我想查看 stderr。我希望标准输出都进入“>>$all_my_out_file”,这是我想保留在不同日志中的错误。有什么想法吗?以上是关于Perl IPC::Run 附加输出并解析标准错误,同时将其保存在一批文件中的主要内容,如果未能解决你的问题,请参考以下文章