在 Ruby 脚本中重定向 stdout 时出现问题

发布于 2024-11-23 22:00:04 字数 660 浏览 3 评论 0原文

我有以下测试 Ruby 脚本:

require 'tempfile'

tempfile = Tempfile.new 'test'
$stderr.reopen tempfile
$stdout.reopen tempfile

puts 'test stdout'
warn 'test stderr'
`mail -s 'test' [email protected] < #{tempfile.path}`

tempfile.close
tempfile.unlink
$stderr.reopen STDERR
$stdout.reopen STDOUT

我收到的电子邮件内容如下:

test stderr

为什么 stderr 正确重定向,但 stdout 不正确?

编辑:为了响应评论,我在 puts 行之后添加了一个 $stdout.flush ,并且它打印正确。所以我会重申我的问题:发生了什么以及为什么冲洗可以修复它?

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' [email protected] < #{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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柏林苍穹下 2024-11-30 22:00:04

标准输出通常会被缓冲,以避免每次写入时都进行系统调用。所以,当你这样说时:

puts 'test stdout'

你实际上只是将该字符串填充到缓冲区中。然后你这样说:

`mail -s 'test' [email protected] < #{tempfile.path}`

并且你的 'test stdout' 字符串仍在缓冲区中,因此当 mail 发送文件的时它不在 tempfile 中内容给你。刷新 $stdout 强制将缓冲区中的所有内容写入磁盘;来自精细手册

将 ios 内的任何缓冲数据刷新到底层操作系统(请注意,这只是 Ruby 内部缓冲;操作系统也可以缓冲数据)。

$stdout.print“无换行符”
$stdout.flush

产生:

没有换行符

标准错误通常是未缓冲的,因此错误消息(应该很少见)立即可见。

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' [email protected] < #{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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文