为什么 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
以确保防止缓冲。
下面的代码是我目前情况的简化。我有一个 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
以确保防止缓冲。