ruby管道,IO和stderr重定向

时间:2016-10-19 01:32:40

标签: ruby-on-rails ruby pipe

我希望有一个ruby程序(rake任务)观察另一个rake任务的输出。输出写入器输出到stderr。我想阅读这些内容。我很难设置它。如果我有一个不断打印东西的作家(stdout_writer.rb):

#!/usr/bin/env ruby
puts 'writing...'
while true
  $stdout.puts '~'
  sleep 1
end

和一个读取它并回显的文件(stdin_reader.rb):

#!/usr/bin/env ruby
puts 'reading...'
while input = ARGF.gets
  puts input
  input.each_line do |line|
    begin
      $stdout.puts "got line #{line}"
    rescue Errno::EPIPE
      exit(74)
    end
  end
end

我试图让它们一起工作,没有任何反应:

$ ./stdout_writer.rb 2>&1 | ./stdin_reader.rb
$ ./stdout_writer.rb | ./stdin_reader.rb
没什么......虽然如果我只是回应到stdin_reader.rb,我得到了我期望的结果:

piousbox@e7440:~/projects/opera_events/sendgrid-example-operaevent$ echo "ok true" | ./stdin_reader.rb
reading...
ok true
got line ok true
piousbox@e7440:~/projects/opera_events/sendgrid-example-operaevent$ 

那么我如何设置一个脚本,将stderr管道传入其中,以便它可以逐行读取?附加信息:这将是一个ubuntu upstart服务script1.rb | script2.rb,其中script1发送消息,script2验证消息是由script1发送的

2 个答案:

答案 0 :(得分:2)

来自stdout_writer.rb的输出由Ruby缓存,因此读者进程看不到它。如果你等待足够长的时间,你应该看到结果以块的形式出现。

您可以在stdout_writer.rb开头的$stdout上关闭缓存并获得setting sync to true期望的结果:

$stdout.sync = true 

答案 1 :(得分:1)

问题似乎是,当stdout_writer无限运行时,stdin_reader永远不会有机会从STDOUT读取stdout_writer作为管道,在这种情况下,正在等待stdout_writerstdin_reader开始阅读之前完成。我通过将while true更改为5.times do来对此进行了测试。如果你这样做,等待5秒,./stdout_writer.rb | ./stdin_reader.rb的结果是

reading...
writing...
got line writing...
~
got line ~
~
got line ~
~
got line ~
~
got line ~
~
got line ~

这不是您的代码本身的问题,但更多的问题是ruby执行在STDOUT | STDIN处理方面有效。

另外,我并不认为我学到了研究这个问题所学到的东西。谢谢你的有趣运动。