2009-10-07 6 views
12

私はインターネットを検索し、STDOUTを2つの異なる場所に送信するための良い解決策を見つけました。同時にログファイルやスクリーンに似ています。ここでは一例です:STDOUTとSTDERRをログファイルとWin32 Perlの画面に送ることはできますか?

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の画面上でいつものように見たいと思っています。エラーメッセージのロギングは、ハッピーメッセージのロギングと同じくらい重要です。別のログファイルにエラーを記録することは良い解決策ではありません。

答えて

5

のような何かをすることによってレベルシェル:

perl stuff.pl 2>&1 

は公式の単語をsupport article hereを参照してください。

this stackoverflow answerを使用すると、シェルからteeを実行できます。

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

それはトリッキーなことかもしれません...私はサードパーティの非perlユーティリティを使用しない解決策を望んでいました...でもコマンドラインでもありません:-) –

+0

依存関係を減らすのに役立つhttp://www.robvanderwoude.com/tee.phpここにperl teeがあります:) – msandiford

+1

「Perlスクリプト'print $ _;' " –

0

STDERRSTDOUTのように動作し、画面と同じログファイルに移動しますか?あなただけの(私はあなたがIO::tee->newへの呼び出しの前か後にこれを行うかどうかぶっきらぼう分からない)

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

STDERRをDUPすることができます。

+1

ええ、私はそれも考えました。しかし、コードのどこにこの行を置いても、エラーメッセージはログファイルに取り込まれません。 –

13

私はLog::Log4perlをこのようなものに使用します。これは、画面、ファイル、データベース、またはあなたが好きなものを含め、あなたのために複数の場所に出力を送信する処理します。一度複雑になってしまったら、自分でこのようなことをするべきではありません。

ファイルハンドルに印刷するのではなく、Log4perlにメッセージを与えて、残りの部分を見つけ出します。私はMastering Perlにそれについての短い紹介があります。これはLog4jに基づいており、Log4jで行うことができるほとんどのことをLog4perlで行うことができます。これは、一度それを知ると、転送可能なスキルになることを意味します。

+0

Log4Perlではファイルハンドルに印刷する必要はありませんか?私はModule :: Buildプロセスによって出力されるprintステートメントのほとんどを制御しないので、すべての出力をリダイレクトする必要があります。 –

+0

私はLog4Perlを見ましたが、ファイルハンドルに印刷する必要があったため、私にはメールに応答していないようです。 –

+1

さて、もしそれがモジュール::ビルドであれば、その問題を解決しましょう。あなたの質問は本当に "Module :: Buildの出力をどのようにキャプチャするのですか?"それは私が最近しているすべてです。サブクラスを作成し、log_ *メソッドをオーバーライドして好きなことをすることができます。 –

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

私は広範囲にLog::Dispatchを使用していますが、私は実際にファイルを画面に表示してしまったものをログに記録するために、上記を使用しました。あなたは窓でstdoutstderrをリダイレクトすることができ

+0

うわー。それはうまくいった。 STDOUTとSTDERRの両方が画面とログファイルに記録されているようですが、不明なソフトウェア例外が発生したことを示す「perl.exe Application Error」ダイアログが常に表示されます。 –

+0

Windows Perlとの互換性に関する実用的な経験はあまりありません。私はLinux上でのみ使用しています。あなたはStrawberry perl対activeestate perlを試しましたか? cygwinをインストールしましたか? – Oesor

+0

私はActiveState PerlとEclipse EPIC IDEを使用しています。 cygwinはありません。 –

3

単に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; 

は、私はしかし、私はStrawberryPerlを使用し、それは動作しますが、Windows上でこれをテストすることを言及する必要があります。

+0

hmmmmが含まれています。これは私のログファイルにSTDERR行を取得しませんでした。私はActivePerlを使用している可能性があります。 –

+0

はチャームのように、またSTDERRと同様に動作します。この解決策は一番上にあるべきです。また肯定的です: 'IO :: Tee'はUbuntu用にパッケージ化されており、これらのシステムへの展開に多くの手助けをします。 –

0

私はあなたに以下のAPIを与える設定可能なダイナミックログでミニマルなperl loggerを書いた:私はこれでテストするには、Windowsボックスを持っていないが、おそらくあなたが結ばハンドルを作るような何かを行うことができ

 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__ 
2

をそれはSTDOUTとSTDOUTRの両方にリダイレクトして、STDOUTとログの両方に出力しますか?

EDIT:後で使用するためにSTDOUTを保存する方法が唯一の不安ですが、最初にWindowsで動作しない場合は、後で使用するためにSTDOUTを保存するための2番目の可能性を追加しました。彼らは両方とも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 @_; 
} 
1

試してみてください。

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}; 

ファイルハンドルを指定していないすべてのprint文は(つまり、任意の通常のメッセージ)ログファイルに出力を送信します。 STDERRファイルハンドルを使用するすべての印刷ステートメント(つまり、すべてのエラー)は、出力をコンソールとログファイルの両方に送信します。

関連する問題