问题
I have the following test Ruby script:
require 'tempfile'
tempfile = Tempfile.new 'test'
$stderr.reopen tempfile
$stdout.reopen tempfile
puts 'test stdout'
warn 'test stderr'
`mail -s 'test' my@email.com < #{tempfile.path}`
tempfile.close
tempfile.unlink
$stderr.reopen STDERR
$stdout.reopen STDOUT
The email that I get has the contents:
test stderr
Why is stderr redirecting properly but not stdout?
Edit: In response to a comment I added a $stdout.flush
after the puts
line and it printed correctly. So I'll restate my question: what was happening and why does the flush fix it?
回答1:
The standard output is generally buffered to avoid a system call for every write. So, when you say this:
puts 'test stdout'
You're actually just stuffing that string into the buffer. Then you say this:
`mail -s 'test' my@email.com < #{tempfile.path}`
and your 'test stdout'
string is still in the buffer so it isn't in tempfile
when mail
sends the file's content to you. Flushing $stdout
forces everything in the buffer to be written to disk; from the fine manual:
Flushes any buffered data within ios to the underlying operating system (note that this is Ruby internal buffering only; the OS may buffer the data as well).
$stdout.print "no newline" $stdout.flush
produces:
no newline
The standard error is often unbuffered so that error messages (which are supposed to be rare) are visible immediately.
来源:https://stackoverflow.com/questions/6700726/problem-redirecting-stdout-in-ruby-script