如果我调用一个命令使用内核#系统在Ruby中,我如何得到它的输出?

system("ls")

当前回答

正如Simon Hürlimann已经解释过的,Open3比反撇号等更安全。

require 'open3'
output = Open3.popen3("ls") { |stdin, stdout, stderr, wait_thr| stdout.read }

注意,块表单将自动关闭stdin, stdout和stderr-否则它们必须显式关闭。

其他回答

正如Simon Hürlimann已经解释过的,Open3比反撇号等更安全。

require 'open3'
output = Open3.popen3("ls") { |stdin, stdout, stderr, wait_thr| stdout.read }

注意,块表单将自动关闭stdin, stdout和stderr-否则它们必须显式关闭。

我在这里没有找到这个,所以添加它,我有一些问题得到完整的输出。

您可以重定向STDERR到STDOUT,如果您想捕获STDERR使用 撇号。 输出= ' grep hosts /private/etc/* 2>&1 '

来源:http://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html

puts `date`
puts $?


Mon Mar  7 19:01:15 PST 2016
pid 13093 exit 0

如果你想使用Kernel#系统将输出重定向到一个文件,你可以这样修改描述符:

以追加模式将stdout和stderr重定向到文件(/tmp/log):

系统(ls状态”,:= > [/ tmp /日志,' '],:呃= > [/ tmp /日志,' '])

对于长时间运行的命令,这将实时存储输出。您还可以使用IO存储输出。管道和重定向它从内核#系统。

虽然使用反勾号或popen通常是您真正想要的,但它实际上并不能回答所提出的问题。可能有捕获系统输出的正当理由(可能是为了自动化测试)。我在谷歌上搜索了一下,找到了一个答案,我想把它贴在这里,以造福他人。

因为我需要这个来测试我的例子使用块设置来捕获标准输出,因为实际的系统调用隐藏在被测试的代码中:

require 'tempfile'

def capture_stdout
  stdout = $stdout.dup
  Tempfile.open 'stdout-redirect' do |temp|
    $stdout.reopen temp.path, 'w+'
    yield if block_given?
    $stdout.reopen stdout
    temp.read
  end
end

该方法使用tempfile存储实际数据来捕获给定块中的任何输出。使用示例:

captured_content = capture_stdout do
  system 'echo foo'
end
puts captured_content

您可以将系统调用替换为任何内部调用系统的东西。如果需要,还可以使用类似的方法来捕获stderr。