如何在Ruby中暂时redirectstderr?

我希望在一个块的持续时间内暂时将stderrredirect到一个Ruby脚本中,以确保在块的末尾将其重置为原始值。

我很难find如何在ruby文档中做到这一点。

在Ruby中, $stderr引用当前用作 stderr的输出stream,而STDERR默认的 stderrstream。 临时将不同的输出stream分配给$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" 

同样的原理也适用于$stdoutSTDOUT

这是一个更抽象的解决scheme(信贷大卫Heinemeier Hansson):

 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 } 

基本上和@ molf的答案一样,并且具有相同的用法:

 require "stringio" def capture_stderr real_stderr, $stderr = $stderr, StringIO.new yield $stderr.string ensure $stderr = real_stderr end 

它使用StringIO非常简洁,保存了$ stderr,就像调用capture_stderr之前的那样。

我喜欢StringIO的答案。 但是,如果您调用外部进程,并且$stderr = StringIO.new不起作用,则可以将stderr写入临时文件:

 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 
Interesting Posts