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

15

有趣的是,你似乎需要做一些特殊的事情。在我的经验中,当我使用“system”运行程序时,子程序的标准输出会发送到父程序的标准输出,这似乎是你想要的。 - Wayne Conrad
这也可能有效:https://dev59.com/PkvSa4cB1Zd3GeqPhdGO#2215986 - Montana Harkin
4个回答

16
与链接的问题一样,答案还是不要使用system,因为system不支持这个功能。

然而,这次的解决方案不是使用反引号,而是使用IO.popen,该函数返回一个 IO 对象,您可以使用它来读取正在生成的输入。

9
谢谢,最终我使用了IO.popen('command_to_run') { |io| while (line = io.gets) do puts line end } - Montana Harkin
快速问题,为什么使用 反引号 不是解决方案或推荐的方法呢?我们正在尝试实现从 rails notes 调用中捕获输出的类似功能。谢谢! - Joshua Pinter
1
反引号会在程序运行完成后将其输出作为字符串返回。OP希望能够在程序仍在运行时访问程序的输出。字符串无法提供这样的功能。popen会给你一个IO对象,允许你在输出到达时处理它。 - sepp2k

3

如果有人想要阅读 stdoutstderr:
重要的是要同时读取它们,而不是先读一个再读另一个。因为程序可以轮流并且甚至同时向 stdoutstderr 输出。所以,你需要使用线程。事实上这一点甚至不是特定于 Ruby 的。

摘自此处

require 'open3'

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

# see: https://dev59.com/SXM_5IYBdhLWcg3w9oMA#1162850
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

0

这是我的解决方案

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,因为程序可以并行地写入这些输出。 - java.is.for.desktop

0

以下是捕获系统命令的标准输出的方法:

output = capture(:stdout) do
  system("pwd") # your system command goes here
end

puts output

简化版:

output = capture(:stdout) { system("pwd") }

同样,我们也可以使用:stderr来捕获标准错误。 active_support/core_ext/kernel/reporting.rb提供了capture方法。
查看该库的代码注释,capture将被弃用,所以不确定当前支持的方法名是什么。

看起来已经被移动到 ActiveSupport::Testing:https://github.com/rails/rails/blob/main/activesupport/lib/active_support/testing/stream.rb - fiedl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接