Rubyでstdoutl/errを標準出力/エラーとファイルの両方に出力する
stdout/stderrをファイルにも出力したくていろいろ調べて、いい感じの解決方法を見つけたのでメモしておく。
ruby-listにmatzが投稿していた(Re: puts,printの出力をファイルにも出力するには)。
これを実行すると、こうなる。
defout = Object.new
defout.instance_eval{@ofile=open("/tmp/test.log", "w")}
class <<defout
def write(str)
STDOUT.write(str)
@ofile.write(str)
end
end
$stdout = defout
puts 'aaa'
$ ruby ./test.rb
aaa
$ cat ./test.log
aaa
なるほど、標準出力と標準エラーにputsされている。便利。
これができると、次はstdoutとstderrの両方をファイルにも出力したくなる。その場合はこうしちゃえばいい。
defout = Object.new
defout.instance_eval{@ofile=open("/tmp/test.log", "a")}
class <<defout
def write(str)
STDOUT.write(str)
@ofile.write(str)
@ofile.flush
end
end
$stdout = defout
deferr = Object.new
deferr.instance_eval{@ofile=open("/tmp/test.log", "a")}
class <<deferr
def write(str)
STDERR.write(str)
@ofile.write(str)
@ofile.flush
end
end
$stderr = deferr
puts 'aaa'
warn 'bbb'
puts 'ccc'
$ ruby ./test.rb
aaa
bbb
ccc
$ cat ./test.log
aaa
bbb
ccc
flushしないとtest.logにstdoutが先に全て出力され、その後にstderrが出力されてしまうようだ。また、この方法だとsystemのような子プロセスの出力はteeされないので注意しないといけない。