在运行ruby system()调用时,如何获取其标准输出?

在运行ruby system()调用时,如何获取其标准输出?,ruby,Ruby,与之类似,我正在运行一个系统命令,但在这种情况下,我需要在命令运行时从命令中输出STDOUT。正如在链接的问题中一样,答案是根本不使用system,因为system不支持这一点 不过,这次的解决方案不是使用反勾号,而是返回一个IO对象,您可以使用它在生成输入时读取输入。这是我的解决方案 def io2stream(shell, &block) Open3.popen3(shell) do |_, stdout, stderr| while line = stdout.gets

与之类似,我正在运行一个系统命令,但在这种情况下,我需要在命令运行时从命令中输出STDOUT。

正如在链接的问题中一样,答案是根本不使用
system
,因为
system
不支持这一点

不过,这次的解决方案不是使用反勾号,而是返回一个IO对象,您可以使用它在生成输入时读取输入。

这是我的解决方案

def io2stream(shell, &block)
  Open3.popen3(shell) do |_, stdout, stderr|
    while line = stdout.gets
      block.call(line)
    end

    while line = stderr.gets
      block.call(line)
    end
  end
end

io2stream("ls -la", &lambda { |str| puts str })

如果有人想阅读标准输出和标准输出:
重要的是同时阅读它们,而不是先读后读。因为程序可以依次输出到stdout和stderr,甚至并行输出。因此,您需要线程。这个事实甚至不是Ruby特有的

从……偷来的


谢谢,我最终使用了
IO.popen('command_to_run'){| IO | while(line=IO.get)do-put-line-end}
奇怪的是,您应该做一些特殊的事情。根据我的经验,当我使用
system
运行一个程序时,子程序的stdout会转到父程序的stdout,这似乎是您想要的。这也可能有效:这只适用于某些程序。应该在两个并行线程中读取stdout和stderr,因为允许程序并行地写入这些输出。
require 'open3'

cmd = './packer_mock.sh'
data = {:out => [], :err => []}

# see: http://stackoverflow.com/a/1162850/83386
Open3.popen3(cmd) do |stdin, stdout, stderr, thread|
  # read each stream from a new thread
  { :out => stdout, :err => stderr }.each do |key, stream|
    Thread.new do
      until (raw_line = stream.gets).nil? do
        parsed_line = Hash[:timestamp => Time.now, :line => "#{raw_line}"]
        # append new lines
        data[key].push parsed_line

        puts "#{key}: #{parsed_line}"
      end
    end
  end

  thread.join # don't exit until the external process is done
end