为什么 Ruby STDOUT 会在我不期望的情况下进行缓冲?

tay*_*low 5 ruby stdout pipe jq

以下代码是我当前情况的简化。我有一个 JSON 日志源,我不断地使用它来获取并写入标准输出puts

#!/usr/bin/env ruby

require "json"

loop do
  puts({ value: "foobar" }.to_json)
  sleep 1
end
Run Code Online (Sandbox Code Playgroud)

我希望能够通过管道将该脚本的输出进行jq进一步处理,但以“流”友好的方式使用unix管道。像这样运行上面的代码:

./my_script | jq
Run Code Online (Sandbox Code Playgroud)

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

我的后续问题是关于使用tail而不是jq. 在我看来,我应该能够以与将文本流传输到 的tail方式相同的方式将其传输到jq,但是这两种方法(无论$stdout.flush有没有调用)都不起作用 - 输出只是空的。

sim*_*nwo 4

正如 @Ry在评论中指出的那样,$stdout.synctrueIRB 中的默认值,但这对于脚本来说不一定相同。

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