简体   繁体   中英

Problem redirecting stdout in Ruby script

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM