【发布时间】:2011-05-17 09:23:53
【问题描述】:
类似于Getting output of system() calls in Ruby,我正在运行系统命令,但在这种情况下,我需要在命令运行时输出STDOUT。
【问题讨论】:
-
奇怪的是你应该做一些特别的事情。根据我的经验,当我使用
system运行程序时,子程序的标准输出会转到父程序的标准输出,这似乎是您想要的。
标签: ruby
类似于Getting output of system() calls in Ruby,我正在运行系统命令,但在这种情况下,我需要在命令运行时输出STDOUT。
【问题讨论】:
system 运行程序时,子程序的标准输出会转到父程序的标准输出,这似乎是您想要的。
标签: ruby
在链接的问题中,答案再次是完全不使用system,因为system 不支持这一点。
不过这次的解决方案不是使用backticks,而是使用IO.popen,它返回一个IO 对象,您可以使用该对象在生成输入时读取它。
【讨论】:
IO.popen('command_to_run') { |io| while (line = io.gets) do puts line end }
如果有人想阅读stdout 和 stderr:
重要的是同时阅读它们,而不是第一个然后另一个。因为程序允许轮流甚至并行输出到stdout和stderr。所以,你需要线程。这个事实甚至不是 Ruby 特有的。
从here窃取。
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
【讨论】:
这是我的解决方案
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 })
【讨论】:
通过以下您可以捕获系统命令的标准输出:
output = capture(:stdout) do
system("pwd") # your system command goes here
end
puts output
缩短版:
output = capture(:stdout) { system("pwd") }
同样,我们也可以使用:stderr 捕获标准错误
capture方法由active_support/core_ext/kernel/reporting.rb
提供查看该库的代码 cmets,capture 将被弃用,因此不确定当前支持的方法名称是什么。
【讨论】: