Perl:Tee将STDOUT + STDERR和STDERR合并为不带CPAN模块的文件

时间:2014-03-21 13:13:27

标签: perl logging stdout stderr tee

我在互联网上搜索了不同的解决方案,而我最接近的是open语句中的练习:

use strict;
use warnings;
use Carp;

# Save previous state
my ($old_out, $old_err);

open($old_out, ">&", \*STDOUT) or 
    croak("Cannot save STDOUT: $!\n");
open($old_err, ">&", \*STDERR) or 
    croak("Cannot save STDERR: $!\n");

my ($fh_OUTLOG);
# Make a filehandle for the tee output
open($fh_OUTLOG, "|-", "tee out_err.log") or
    croak("Cannot open filehandle to tee to log file: $!\n");

# Duplicate STDOUT and STDERR to the filehandle
open(STDOUT, ">&", $fh_OUTLOG) or
    croak("Cannot duplicate STDOUT to filehandle: $!\n");

open(STDERR, ">&", $fh_OUTLOG) or
    croak("Cannot duplicate STDERR to filehandle: $!\n");

# Code...


# Restore STDOUT 
open(STDOUT, ">&", $old_out) or
    croak("Cannot restore STDOUT: $!\n");

# Close the filehandle            
close $fh_OUTLOG        
    or croak( ($!) ? "Error closing fh_OUTLOG: $!"
                  : "Exit status $? from tee log.out");

# Restore STDERR   
open(STDERR, ">&", $old_err) or
     croak("Cannot restore STDERR: $!\n");

但是这段代码不会产生STDERR的日志文件,我也不知道如何添加它。解决方案的标准是:

  1. Perl v 5.8.3。
  2. 没有CPAN模块。
  3. 没有Bash额外命令来启动脚本。
  4. 我在考虑为STDERR使用一些tee解决方案:

    open(STDERR, "| tee log.err");
    open(STDERR, ">&", $fh_OUTLOG);
    

    但是使用它会在执行结束时挂起脚本。 (想想开球儿童过程仍然活着)。但是如果我最终试图杀死它,脚本仍会挂起。

    my $pid_std_err = open(STDERR, "| tee log.err") or
         croak("Cannot tee filehandle STDERR to log.err: $!\n");
    
    # Code... 
    
    kill -9, $pid_std_err;
    

1 个答案:

答案 0 :(得分:0)

  1. 创建两个管道并将它们与STDOUT和STDERR相关联。
  2. 创建一个使用IO :: Select的任务(线程,进程等)从这两个管道中读取。
  3. 该任务将从这些管道中读取的内容放在适当的文件中。