Rubyスクリプトでstderrを一時的にリダイレクトしたい場合は、ブロックの最後に元の値にリセットしてください。Rubyで標準エラー出力を一時的にリダイレクトするにはどうすればよいですか?
ルビーのドキュメントでこれを行う方法がわかりませんでした。 STDERR
がデフォルト stderrのストリームであるのに対し、Rubyで
Rubyスクリプトでstderrを一時的にリダイレクトしたい場合は、ブロックの最後に元の値にリセットしてください。Rubyで標準エラー出力を一時的にリダイレクトするにはどうすればよいですか?
ルビーのドキュメントでこれを行う方法がわかりませんでした。 STDERR
がデフォルト stderrのストリームであるのに対し、Rubyで
、$stderr
は、現在stderrのよう使用される出力ストリームを指します。一時的に別の出力ストリームを$stderr
に割り当てるのは簡単です。
require "stringio"
def capture_stderr
# The output stream must be an IO-like object. In this case we capture it in
# an in-memory IO object so we can return the string value. You can assign any
# IO object here.
previous_stderr, $stderr = $stderr, StringIO.new
yield
$stderr.string
ensure
# Restore the previous value of stderr (typically equal to STDERR).
$stderr = previous_stderr
end
今、あなたは、次の操作を行うことができます
captured_output = capture_stderr do
# Does not output anything directly.
$stderr.puts "test"
end
captured_output
#=> "test\n"
同じ原理も$stdout
とSTDOUT
のために動作します。
私はこれをCのstderr(ファイル記述子2)に直接書き込む関数(RubyVM :: InstructionSequence)で使用しています。これでうまくいくのだろうか?私は、Rubyランタイムによって呼び出される低レベルのC関数の標準エラー出力を抑制しようとしています。 – horseyguy
@banister:はい、うまくいくはずです。 Rubyは '$ stderr'を内部的に使用します。そして、何らかの理由で(バグになる)それが当てはまらない場合、あなたのRubyコードでは残念ながらあなたはそれについて何もすることができません。 – molf
それは動作します!素晴らしい! :) thanks – horseyguy
molfの答え@と本質的に同じ、と同じ用法があります。
require "stringio"
def capture_stderr
real_stderr, $stderr = $stderr, StringIO.new
yield
$stderr.string
ensure
$stderr = real_stderr
end
をそれは非常にわずかにより簡潔にStringIOを使用し、capture_stderrが呼び出される前だった何として$の標準エラー出力を保持します。ここで
良い機能強化! – molf
は、より抽象的な溶液(クレジットはデイビット・ハインメアー・ハンスソンに行く)です:
def silence_streams(*streams)
on_hold = streams.collect { |stream| stream.dup }
streams.each do |stream|
stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
stream.sync = true
end
yield
ensure
streams.each_with_index do |stream, i|
stream.reopen(on_hold[i])
end
end
は使用方法:
silence_streams(STDERR) { do_something }
私のRUBY_PLATFORM == "i386-mingw32"なので、これは私のWindowsマシンでは動作しません。人々が奇妙な環境で動いているかも知れないので、このために文字列の照合をお勧めします。 – Nossidge
私はのStringIO答えが好き。
require 'tempfile'
def capture_stderr
backup_stderr = STDERR.dup
begin
Tempfile.open("captured_stderr") do |f|
STDERR.reopen(f)
yield
f.rewind
f.read
end
ensure
STDERR.reopen backup_stderr
end
end
関連質問:http://stackoverflow.com/questions/3018595/how-doあなたが外部プロセスを呼び出している、と
$stderr = StringIO.new
が動作しない場合でも、あなたは一時ファイルに標準エラー出力を書き出すかもしれません-i-redirect-stderr-and-styout-to-a-ruby-script –