如何从Ruby程序内部调用shell命令?然后如何将这些命令的输出返回到Ruby中?


当前回答

在我看来,这是关于在Ruby中运行shell脚本的最好的文章:“在Ruby中运行shell命令的6种方法”。

如果您只需要获得输出,请使用反勾号。

我需要更高级的东西,比如STDOUT和STDERR,所以我使用了Open4 gem。这里已经解释了所有的方法。

其他回答

在我看来,这是关于在Ruby中运行shell脚本的最好的文章:“在Ruby中运行shell命令的6种方法”。

如果您只需要获得输出,请使用反勾号。

我需要更高级的东西,比如STDOUT和STDERR,所以我使用了Open4 gem。这里已经解释了所有的方法。

在这些机制之间进行选择时需要考虑的一些事情是:

你只是想要stdout还是 也需要stderr ?甚至 分离出来吗? 你的产出有多大?你想要 将整个结果保存在内存中? 你想读一些你的吗 在子进程静止时输出 跑步吗? 你需要结果代码吗? 你需要一个Ruby对象吗 表示流程并允许您 按需杀死它?

您可能需要简单的反撇号(' ')、system()和IO。popen到成熟的Kernel.fork/Kernel。执行IO。pipe和IO.select。

如果子进程执行时间过长,您可能还想在混合过程中加入超时。

不幸的是,这在很大程度上取决于情况。

给定像attrib这样的命令:

require 'open3'

a="attrib"
Open3.popen3(a) do |stdin, stdout, stderr|
  puts stdout.read
end

我发现,虽然这种方法不像

system("thecommand")

or

`thecommand`

在反引号中,与其他方法相比,此方法的一个优点是 反勾号似乎不让我把我运行的命令/存储我想要运行的命令在一个变量中,而system(" command")似乎不让我得到输出,而这个方法让我做这两件事,它让我访问stdin, stdout和stderr独立。

参见“在ruby中执行命令”和ruby的Open3文档。

不确定shell命令。我使用以下命令将系统命令的输出捕获到变量val中:

val = capture(:stdout) do
  system("pwd")
end

puts val

缩短版本:

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

捕获方法由active_support/core_ext/kernel/reporting.rb提供

类似地,我们也可以用:stderr捕获标准错误

这个解释是基于我的一个朋友写的带注释的Ruby脚本。如果您想改进脚本,请在链接中进行更新。

首先,请注意,当Ruby调用shell时,它通常调用/bin/sh,而不是Bash。在所有系统上/bin/sh不支持某些Bash语法。

以下是执行shell脚本的方法:

cmd = "echo 'hi'" # Sample string that can be used

Kernel#` , commonly called backticks – `cmd` This is like many other languages, including Bash, PHP, and Perl. Returns the result (i.e. standard output) of the shell command. Docs: http://ruby-doc.org/core/Kernel.html#method-i-60 value = `echo 'hi'` value = `#{cmd}` Built-in syntax, %x( cmd ) Following the x character is a delimiter, which can be any character. If the delimiter is one of the characters (, [, {, or <, the literal consists of the characters up to the matching closing delimiter, taking account of nested delimiter pairs. For all other delimiters, the literal comprises the characters up to the next occurrence of the delimiter character. String interpolation #{ ... } is allowed. Returns the result (i.e. standard output) of the shell command, just like the backticks. Docs: https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Percent+Strings value = %x( echo 'hi' ) value = %x[ #{cmd} ] Kernel#system Executes the given command in a subshell. Returns true if the command was found and run successfully, false otherwise. Docs: http://ruby-doc.org/core/Kernel.html#method-i-system wasGood = system( "echo 'hi'" ) wasGood = system( cmd ) Kernel#exec Replaces the current process by running the given external command. Returns none, the current process is replaced and never continues. Docs: http://ruby-doc.org/core/Kernel.html#method-i-exec exec( "echo 'hi'" ) exec( cmd ) # Note: this will never be reached because of the line above

这里有一些额外的建议: $ ?,与$CHILD_STATUS相同,如果使用反勾号、system()或%x{},则访问最后一个系统执行命令的状态。 然后你可以访问exitstatus和pid属性:

$?.exitstatus

更多阅读请参见:

http://www.elctech.com/blog/i-m-in-ur-commandline-executin-ma-commands http://blog.jayfields.com/2006/06/ruby-kernel-system-exec-and-x.html http://tech.natemurray.com/2007/03/ruby-shell-commands.html