обо всем по порядку.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;
};
}
Каждый из дескрипторов выходного файла закроется, когда на них больше не будет ссылаться что-либо -- в данном случае в конце этого фрагмента.
Я исправил ваш @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:
: обновлено в соответствии с вашим комментарием. Все stdout отправляются в один файл, а команда stderr из команды подается во встроенную подпрограмму. Также исправленоглупая опечатка (для синтаксиса был псевдокод не Perl).