我可以给STDOUT和STDERR到一个日志文件,并也于Win32的Perl的屏幕?(Can I s

2019-07-21 06:56发布

我在网上搜索,发现了发球STDOUT 2个不同的地方一些很好的解决方案。 就像到一个日志文件,并也同时在屏幕上。 这里有一个例子:

use IO::Tee;
my $log_filename = "log.txt";
my $log_filehandle;
open( $log_filehandle, '>>', $log_filename )
  or die("Can't open $log_filename for append: $!");
my $tee = IO::Tee->new( $log_filehandle, \*STDOUT );
select $tee;

但这种方法留下STDERR只会在屏幕上,我想STDERR到两个屏幕,并且还到STDOUT被记录到相同的日志文件。 是否可能?

我的任务是让我的构建过程记录下来,但我也希望看到它在我的IDE的屏幕像往常一样。 并记录错误信息是一样登录开心的消息一样重要。 并获得记录到一个单独的日志文件中的错误不是一个很好的解决方案。

Answer 1:

您可以重定向stderrstdout在窗口通过执行类似外壳级别:

perl stuff.pl 2>&1

见支持文章在这里的官方消息。

然后,你可以使用这个计算器的答案做一个tee从壳。

perl stuff.pl 2>&1 | tee stuff.txt


Answer 2:

我使用日志:: Log4perl这样的事情。 它处理的输出发送到你的多个位置,包括屏幕,文件,数据库,或其他任何你喜欢的。 一旦你得到哪怕是一点点复杂,你不应该做你自己的这些东西。

相反,打印到文件句柄,你只要给Log4perl一个消息,并计算出的其余部分。 我有一个简短的介绍它掌握的Perl 。 它是基于Log4j的,而且大部分可以在Log4j,你可以在Log4perl,这也意味着,一旦你知道它,它变成一个可转移技能做的做的东西。



Answer 3:

use PerlIO::Util;
*STDOUT->push_layer(tee => ">>/dir/dir/file");
*STDERR->push_layer(tee => ">>/dir/dir/file");

虽然我使用日志::派遣广泛,我用上面的记录实际上得到显示的内容到屏幕上一个文件。



Answer 4:

简单地重新分配STDERR文件句柄...

use IO::Tee;
my $log_filename = "log.txt";
my $log_filehandle;
open( $log_filehandle, '>>', $log_filename )
  or die("Can't open $log_filename for append: $!");
my $tee = IO::Tee->new( $log_filehandle, \*STDOUT );
*STDERR = *$tee{IO};
select $tee;

应该提到,我测试在Windows操作系统上,它的工作原理,但我用StrawberryPerl。



Answer 5:

我没有在Windows中测试这个,但也许你可以做这样的事情作出绑手柄,将打印到标准输出和一个日志,然后重定向STDOUT和STDERR呢?

编辑:我唯一担心的是存储STDOUT供以后使用的方法,我已经添加了存储STDOUT供以后使用,必须在第一不工作在Windows上第二个可能性。 他们都为我工作在Linux上。

#!/usr/bin/perl

use strict;
use warnings;

tie *NEWOUT, 'MyHandle', 'test.log';
*STDOUT = *NEWOUT;
*STDERR = *NEWOUT;

print "Print\n";
warn "Warn\n";

package MyHandle;

sub TIEHANDLE {
  my $class = shift;
  my $filename = shift;

  open my $fh, '>', $filename or die "Could not open file $filename";

  ## Use one of these next two lines to store STDOUT for later use.
  ## Both work for me on Linux, if one does not work on Windows try the other.
  open(OLDSTDOUT, '>&STDOUT') or die "Could not store STDOUT";
  #*OLDSTDOUT = *STDOUT;

  my $self = {
    loghandle => $fh,
    logfilename => $filename,
    stdout => \*OLDSTDOUT,
  };

  bless $self, $class;

  return $self;
}

sub PRINT {
  my $self = shift;
  my $log = $self->{loghandle};
  my $stdout = $self->{stdout};
  print $log @_;
  print $stdout @_;
}


Answer 6:

尝试:

my logfh;
my $logfn = "some/path/to/file.log";
open ($logfh, '>',$logfn ) or die "Error opening logfile $logfn\n";
my $tee = IO::Tee->new( $logfh);
my $tee2 = IO::Tee->new( $logfh, \*STDOUT );
# all naked print statements will send output to log file
select($tee);
# all STDERR print statements will send output to console
*STDERR = *$tee2{IO};

没有指定一个文件句柄的所有打印语句(即任何常规邮件)将输出发送到日志文件。 使用该STDERR文件句柄的所有打印语句(即所有错误)将输出发送到控制台和日志文件两者。



Answer 7:

所以,你要STDERR表现得像STDOUT ,来到这两个屏幕,相同的日志文件? 你可以DUP STDERR

open(STDERR, ">&STDOUT") or warn "failed to dup STDOUT:$!";

(我不知道随便你是否会做这之前或通话后IO::tee->new )。



Answer 8:

我写了一个简约的Perl记录器可配置动态记录给你以下API:

        use strict ; use warnings ; use Exporter;
        use Configurator ; 
        use Logger ; 


        #   anonymous hash !!!
        our $confHolder = () ; 

        sub main {

                # strip the remote path and keep the bare name
                $0=~m/^(.*)(\\|\/)(.*)\.([a-z]*)/; 
                my $MyBareName = $3; 
                my $RunDir= $1 ; 

                # create the configurator object 
                my $objConfigurator = new Configurator($RunDir , $MyBareName ); 
                # get the hash having the vars 
                $confHolder = $objConfigurator ->getConfHolder () ; 
                # pring the hash vars 
                print $objConfigurator->dumpIni();  

                my $objLogger = new Logger (\$confHolder) ; 
                $objLogger->LogMsg  (   " START MAIN " ) ;  

                $objLogger->LogMsg  (   "my \$RunDir is $RunDir" ) ; 
                $objLogger->LogMsg  (   "this is a simple message" ) ; 
                $objLogger->LogErrorMsg (   "This is an error message " ) ; 
                $objLogger->LogWarningMsg   (   "This is a warning message " ) ; 
                $objLogger->LogInfoMsg  (   "This is a info message " ) ; 
                $objLogger->LogDebugMsg (   "This is a debug message " ) ; 
                $objLogger->LogTraceMsg (   "This is a trace message " ) ; 
                $objLogger->LogMsg  (   "using the following log file " .  "$confHolder->{'LogFile'}" ) ; 
                $objLogger->LogMsg  (   " STOP MAIN \n\n" ) ; 

        } #eof main 



        #Action !!!
        main(); 

        1 ; 

        __END__


文章来源: Can I send STDOUT and STDERR to a log file and also to the screen in Win32 Perl?