module Kernel

def capture(stream)

stream # => "error\n"
stream = capture(:stderr) { system('echo error 1>&2') }

stream # => "notice\n"
stream = capture(:stdout) { system('echo notice') }

even for subprocesses:

stream # => "error\n"
stream = capture(:stderr) { warn 'error' }

stream # => "notice\n"
stream = capture(:stdout) { puts 'notice' }

Captures the given stream and returns it:
def capture(stream)
  ActiveSupport::Deprecation.warn(
    "`#capture(stream)` is deprecated and will be removed in the next release."
  ) #not thread-safe
  stream = stream.to_s
  captured_stream = Tempfile.new(stream)
  stream_io = eval("$#{stream}")
  origin_stream = stream_io.dup
  stream_io.reopen(captured_stream)
  yield
  stream_io.rewind
  return captured_stream.read
ensure
  captured_stream.close
  captured_stream.unlink
  stream_io.reopen(origin_stream)
end