Проблема перенаправления стандартного вывода в сценарии Ruby - PullRequest
2 голосов
/ 15 июля 2011

У меня есть следующий тестовый скрипт Ruby:

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

Полученное письмо содержит:

test stderr

Почему stderr перенаправляет правильно, а не stdout?

Редактировать: В ответ на комментарий я добавил $stdout.flush после строки puts, и он напечатан правильно. Поэтому я повторю свой вопрос: что происходило и почему флеш исправляет это?

1 Ответ

4 голосов
/ 15 июля 2011

Стандартный вывод обычно буферизируется, чтобы избежать системного вызова для каждой записи.Итак, когда вы говорите это:

puts 'test stdout'

На самом деле вы просто вставляете эту строку в буфер.Затем вы говорите следующее:

`mail -s 'test' my@email.com < #{tempfile.path}`

, и ваша строка 'test stdout' все еще находится в буфере, поэтому ее нет в tempfile, когда mail отправляет вам содержимое файла.Сброс $stdout заставляет все в буфере записываться на диск;из тонкого руководства :

Сбрасывает любые буферизованные данные в ios в базовую операционную систему (обратите внимание, что это только внутренняя буферизация Ruby; ОС также может буферизовать данные).

$stdout.print "no newline"
$stdout.flush

производит:

no newline

Стандартная ошибка часто не буферизуется, поэтому сообщения об ошибках (которые должны быть редкими) видны сразу.

...