如果我调用一个命令使用内核#系统在Ruby中,我如何得到它的输出?
system("ls")
如果我调用一个命令使用内核#系统在Ruby中,我如何得到它的输出?
system("ls")
当前回答
将标准输出捕获到名为val的变量中最简单的解决方案:
val = capture(:stdout) do
system("pwd")
end
puts val
缩短版本:
val = capture(:stdout) { system("ls") }
捕获方法由 active_support / core_ext /内核/ reporting.rb
类似地,我们也可以用:stderr捕获标准错误
其他回答
puts `date`
puts $?
Mon Mar 7 19:01:15 PST 2016
pid 13093 exit 0
你可以用反勾号:
`ls`
另一种方法是:
f = open("|ls")
foo = f.read()
注意,这是open中“ls”前面的“pipe”字符。这也可用于将数据送入程序的标准输入以及读取其标准输出。
请注意,所有向系统传递包含用户提供值的字符串的解决方案,%x[]等都是不安全的!不安全实际上意味着:用户可以触发代码在上下文中运行,并具有程序的所有权限。
据我所知,只有系统和Open3。popen3在Ruby 1.8中提供了一个安全/转义的变体。在Ruby 1.9中,IO::popen也接受数组。
只需将每个选项和参数作为数组传递给其中一个调用。
如果你不仅需要退出状态,还需要结果,你可能会使用Open3.popen3:
require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3('usermod', '-p', @options['shadow'], @options['username'])
stdout.gets(nil)
stdout.close
stderr.gets(nil)
stderr.close
exit_code = wait_thr.value
注意,块表单将自动关闭stdin, stdout和stderr-否则它们必须显式关闭。
更多信息:在Ruby中形成卫生shell命令或系统调用
虽然使用反勾号或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。