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?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.