Hatena::ブログ(Diary)

himazu blog このページをアンテナに追加 RSSフィード

 | 

2007-08-09

STDOUTとSTDERRをファイルにも出力するようにする

Perlで書いたプログラムを極力変更せずに、STDOUTとSTDERRを通常通り出力させたまま、それに加えてファイルに出力したくなった。そのプログラムはシステム管理的コマンドで、コマンド行から使い、その出力をリアルタイムで見るのだが、出力をファイルにも保存しておきたい。STDERRも記録したいのは、dieしたときなどはSTDERRに出てしまうからである。

そのPerlプログラムの名前をfooとしよう。fooを直接起動するのではなく、以下のようなシェルスクリプト(foowrapperと呼ぼう)から呼び出すことにすれば比較的簡単に目標はほぼ達成できる。

#!/bin/sh
foo 2>&1 | tee file

しかし、これではちょっと不便だ。fooとfoowrapperの両方が必要になる。fooがPATHの中にないといけない。foowrapperの中にfooを絶対パスで書くと、fooの場所を動かしたときに動かなくなる。

少し調べたら以下のような例が出ている。

open(STDOUT, "| tee file");

しかし、STDERRを加えて以下のようにすると、プログラムが終了しなくなる。改行を端末から入力すると終了するが、それは鬱陶しい。

open(STDOUT, "| tee file");
open(STDERR, "| tee -a file");

print "hi\n";
print STDERR "ho\n";

そもそも、teeを2つも起動するのは無駄だ。以下のようにすればteeは1つで済む。

open(STDOUT, "| tee file");
open(STDERR, ">&STDOUT");

print "hi\n";
print STDERR "ho\n";

これでもまだプログラムが終了しないままだ。

プログラムが終了しないのは、ファイルを閉じることができないからだろう。fooが開いているのはSTDIN, STDOUT, STDERRだけだ。試しにSTDOUTを閉じると、事態は悪化した。改行を入力しても終了しなくなった。

open(STDOUT, "| tee file");
open(STDERR, ">&STDOUT");

print "hi\n";
print STDERR "ho\n";
close(STDOUT);

STDERRを閉じて、更にSTDOUTを閉じたら、ちゃんと終了するようになった。

open(STDOUT, "| tee file");
open(STDERR, ">&STDOUT");

print "hi\n";
print STDERR "ho\n";
close(STDERR);
close(STDOUT);

ただし、fooを呼び出した側で標準エラー出力を見ても何も出てこず、すべて標準出力に出てしまう。外から見て標準エラー出力が普通に使われているようにしたまま、ファイルにも記録するのにはもう少し手間がかかりそうだ。

上記のことはRedHat Linuxでやっていたのだが、ためしにSolarisとCygwinで試したら同じ結果になった。Perlのバージョンは5.8である。Perlの標準出力・標準エラー出力の挙動について、これらのプラットフォームは同じ挙動を示している。

likklikk 2007/08/10 15:08 標準出力がリアルタイムに出力されなくて良いのであれば、IO::Captureで。

my $capture = IO::Capture::Stdout->new();
$capture->start();
print STDOUT ”Hello¥n”;
print STDOUT ”Perl¥n”;
$capture->stop();

open( LOG, ”>stdout.txt” );
print LOG $capture->read();
print STDOUT $capture->read();
close LOG

標準エラーは同様にIO::Capture::Stderr->new()

himazubloghimazublog 2007/08/10 19:38 コメントありがとうございます。IO::Captureは知りませんでした。

私の状況では標準出力がリアルタイムに出力されないと、管理に使うコマンドではちょっと困るのです。それと、プログラム内で外部コマンドを起動してまして、IO::Capture::Stdoutではそれを面倒見てくれませんね。

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

 | 
カレンダー
2005 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 08 | 09 | 10 | 11 |
2008 | 01 | 02 | 03 | 05 | 06 | 08 | 09 | 10 |
2009 | 01 | 02 | 04 | 10 | 11 | 12 |
2010 | 07 | 08 |
2011 | 01 | 03 | 07 | 08 |
2012 | 03 | 09 | 10 | 11 |
2013 | 04 | 06 | 07 | 09 | 10 | 11 |
2014 | 01 | 02 | 03 |
Connection: close