为什么 Ruby STDOUT 在我不期望的时候进行缓冲?

Why is Ruby STDOUT buffering when I don't expect it to?

下面的代码是我目前情况的简化。我有一个 JSON 日志源,我用 puts.

不断获取并写入标准输出
#!/usr/bin/env ruby

require "json"

loop do
  puts({ value: "foobar" }.to_json)
  sleep 1
end

我希望能够将此脚本的输出通过管道传输到 jq 以进行进一步处理,但是以 'stream' 友好的方式,使用 unix 管道。 运行 上面的代码是这样的:

./my_script | jq

结果为空输出。但是,如果我在 sleep 调用之后放置一个 exit 语句,输出将按预期通过管道发送到 jq。我能够通过在 puts 调用之后调用 $stdout.flush 来解决这个问题。虽然它现在正在工作,但我不确定为什么。 $stdout.sync 默认设置为 true(参见 IO#sync)。在我看来,如果启用了同步,那么 Ruby 应该不会进行输出缓冲,并且不需要调用 $stdout.flush - 但确实如此。

我的后续问题是关于使用 tail 而不是 jq。在我看来,我应该能够像将文本流传输到 jq 一样将文本流传输到 tail,但是这两种方法(使用或不使用 $stdout.flush 调用)都不起作用- 输出只是空的。

正如@Ry 指出的 $stdout.sync 在 IRB 中默认为 true,但这对于脚本来说不一定相同。

所以你应该设置$stdout.sync = true以确保防止缓冲。