[英]Perl: Display STDOUT and STDERR in different colors on Windows
[英]capturing STDERR from commands and pipe STDOUT in perl under windows
我正在使用一个Perl脚本,它使用系统来运行一系列外部命令,如下所示:
system( "command1 | command2 | command3 > outfile" );
现在我想将所有这些命令中的STDERR捕获到一个文件中。 这适用于OS X:
system( "command1 2> error.log | command2 2> error.log | command3 2> error.log > outfile" );
但不是在Windows中,我得到错误:
“进程无法访问该文件,因为它正被另一个进程使用”
有没有解决方法? 我需要它是便携式的,所以如果可能的话,我想避免使用模块。 提前致谢。
没有shell,没有临时文件,也没有来自核心之外的东西。
use strict;
use warnings;
use IPC::Open3 qw( open3 );
my @pids;
{
my @cmd1 = ( 'perl', '-E', q{say for qw( ABC DEF );} );
my @cmd2 = ( 'perl', '-pe', q{$_=lc; warn(qq{x\n});} );
my @cmd3 = ( 'perl', '-pe', q{$_=ucfirst; warn(qq{y\n});} );
my $nul = $^O eq 'MSWin32' ? 'nul' : '/dev/null';
open(local *CHILD_STDIN, '<', $nul ) or die $!;
open(local *CHILD_STDOUT, '>', 'outfile' ) or die $!;
open(local *CHILD_STDERR, '>', 'error.log') or die $!;
push @pids, open3('<&CHILD_STDIN', local *PIPE1, '>&CHILD_STDERR', @cmd1);
push @pids, open3('<&PIPE1', local *PIPE2, '>&CHILD_STDERR', @cmd2);
push @pids, open3('<&PIPE2', '>&CHILD_STDOUT', '>&CHILD_STDERR', @cmd3);
*CHILD_STDIN if 0; # Silence warning. Already closed by open3.
*PIPE1 if 0; # Silence warning. Already closed by open3.
*PIPE2 if 0; # Silence warning. Already closed by open3.
close(CHILD_STDOUT);
close(CHILD_STDERR);
}
waitpid($_, 0) for @pids;
那是因为'>'不喜欢共享文件。 为管道的每个阶段提供自己的错误日志,然后在管道完成后执行类似的操作:
system("cat error1.log erorr2.log error3.log > error.log");
这是一种独立于平台的聚合日志的方法:
my @error_logs = qw( error1.log error2.log error3.log );
open my $errlog, ">>", "error.log" || die "probelm opening error log: $!";
foreach my $sublog ( @error_logs ) {
open my $fh, "<", $sublog || die "oh boy: $sublog: $!";
print "$sublog:"
print $errlog while $fh;
close $fh;
}
close $errlog;
但是如果你决定以这种方式倾斜,那么也存在IO :: Cat和File :: Cat 。
1)更正了不共享文件的自私公文的名称。
2)添加日志文件集合
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.