【问题标题】:Streaming data from STDOUT从 STDOUT 流式传输数据
【发布时间】:2012-05-02 07:01:41
【问题描述】:

所以我有以下代码:

reader.rb

require 'open4'

def streamer(stdout)
  begin
    loop do
      data = stdout.read_nonblock(8)
      print data
    end
  rescue Errno::EAGAIN
    retry
  rescue EOFError
    puts 'End of file'
  end
end
pid, stdin, stdout, stderr = Open4::popen4 "ruby threader.rb"
stdout.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
streamer(stdout)

threader.rb

10.times do
  $stdout.puts "test"
  sleep 1
end

一个 ruby​​ 脚本是一个简单的微调器,每秒都会输出到标准输出。

另一个用于运行该脚本,我想捕获传入的数据。所以我希望流从标准输出非阻塞读取。

我似乎无法让它工作。我想我正确设置了 fctnl O_NONBLOCK 标志,但也许我没有。

【问题讨论】:

  • 请直接在此处发布代码而不是链接到它,如果将来不再存在链接,它可以防止问题变得无用。

标签: ruby


【解决方案1】:

您的代码运行良好。您只缺少一件,那就是刷新threader 的输出缓冲区。

问题是 STDOUT 几乎总是被缓冲,在这种情况下,除非明确告知,否则缓冲区不会被刷新,直到线程退出之后。

这就是为什么读者什么都看不到的原因,然后当线程退出并且 STDOUT 被刷新时,它会突然得到一个输出。

所以这个测试的简单修复是:

10.times do
  $stdout.puts "test"
  $stdout.flush
  sleep 1
end

但是请注意,由于您正在使用 NONBLOCK 阅读,您的阅读器将忙于循环(!)消耗 100% 的 CPU。为了防止busylooping,您真正应该做的是在读取之前等待传入数据。

这可以通过IO.select来完成:

...
loop do
  IO.select([stdout]) # <- waits for data (any data, even 1 byte)
  data = stdout.read_nonblock(8)
  print data
end  
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-20
    • 2020-04-07
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    相关资源
    最近更新 更多