[perl] 標準出力と標準エラー出力をファイルに記録しつつ出力する
必要になったので調べていたのですが、himazu blog さんの、STDOUTとSTDERRをファイルにも出力するようにする では、解決していないようなので自分で考えてみました。
これにより、本文中の print 文には一切触れずに、STDOUT (標準出力) と STDERR (標準エラー出力) をこっそりロギングする仕組みを追加でき、STDERR に出る warning も捕捉できるので、とても便利だと思います。
この機能の実現に必要な、ファイルハンドルを多重化するしくみは、CPAN モジュールで、IO::Tee と File::Tee が見つかったのですが、どうやら、File::Tee が簡単に使えそうです。
ひとつ残念なところは、File::Tee は Windows に対応していない点です。
せっかく前処理部分を書けるので、無駄にタイムスタンプ機能などを追加してみました。
記録例 (output.log)
これにより、本文中の print 文には一切触れずに、STDOUT (標準出力) と STDERR (標準エラー出力) をこっそりロギングする仕組みを追加でき、STDERR に出る warning も捕捉できるので、とても便利だと思います。
この機能の実現に必要な、ファイルハンドルを多重化するしくみは、CPAN モジュールで、IO::Tee と File::Tee が見つかったのですが、どうやら、File::Tee が簡単に使えそうです。
ひとつ残念なところは、File::Tee は Windows に対応していない点です。
use File::Tee qw(tee);
open(my $log_fh, '>>', 'output.log');
tee(STDOUT, $log_fh);
tee(STDERR, $log_fh);
print STDERR "stderr\n";
print "stdout\n";
warn "warning";
system("echo system stdout");
system("echo system stderr >&2");
せっかく前処理部分を書けるので、無駄にタイムスタンプ機能などを追加してみました。
use DateTime;
use DateTime::TimeZone;
use File::Tee qw(tee);
my $tzlocal = DateTime::TimeZone->new(name => 'local');
sub get_prepender {
my $label = shift;
return sub {
my $data = shift;
return join(' ',
DateTime->now()->set_time_zone($tzlocal)->datetime(),
$label, $data
);
};
}
open(my $log_fh, '>>', 'output.log');
tee(STDOUT, {open => $log_fh, preprocess => get_prepender('STDOUT')});
tee(STDERR, {open => $log_fh, preprocess => get_prepender('STDERR')});
print "stdout\n";
print STDERR "stderr\n";
warn "warning";
system("echo system stdout");
system("echo system stderr >&2");
記録例 (output.log)
2009-07-17T00:12:53 STDOUT stdout 2009-07-17T00:12:53 STDOUT system stdout 2009-07-17T00:12:53 STDERR stderr 2009-07-17T00:12:53 STDERR warning at redirect.pl line 29. 2009-07-17T00:12:53 STDERR system stderr
コメント
コメントを投稿