在Ruby脚本中运行命令行命令


Answers:


209

是。有几种方法:


一个。使用%x或“`”:

%x(echo hi) #=> "hi\n"
%x(echo hi >&2) #=> "" (prints 'hi' to stderr)

`echo hi` #=> "hi\n"
`echo hi >&2` #=> "" (prints 'hi' to stderr)

这些方法将返回标准输出,并将标准错误重定向到程序的标准输出。


b。用途system

system 'echo hi' #=> true (prints 'hi')
system 'echo hi >&2' #=> true (prints 'hi' to stderr)
system 'exit 1' #=> nil

true如果命令成功,则返回此方法。它将所有输出重定向到程序的输出。


C。用途exec

fork { exec 'sleep 60' } # you see a new process in top, "sleep", but no extra ruby process. 
exec 'echo hi' # prints 'hi'
# the code will never get here.

该命令将当前进程替换为该命令创建的进程。


d。(ruby 1.9)使用spawn

spawn 'sleep 1; echo one' #=> 430
spawn 'echo two' #=> 431
sleep 2
# This program will print "two\none".

此方法不等待进程退出并返回PID。


e。用途IO.popen

io = IO.popen 'cat', 'r+'
$stdout = io
puts 'hi'
$stdout = IO.new 0
p io.read(1)
io.close
# prints '"h"'.

此方法将返回一个IO代表新进程的输入/输出的对象。这也是目前我所知道的唯一输入程序的方法。


F。使用Open3(在1.9.2及更高版本上)

require 'open3'

stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.successful?
  puts stdout
else
  STDERR.puts "OH NO!"
end

Open3还有其他几个功能可以显式访问两个输出流。它类似于popen,但使您可以访问stderr。


奖金招:io = IO.popen 'cat > out.log', 'r+'; 将命令的输出写入“ out.log”
Narfanator

1
每个优点和缺点是什么。我该如何决定使用哪个?如何使用FileUtils[ ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html]
2013年

1
我正在使用exec执行SVN命令。我不希望exec的输出出现在控制台上。我想重定向它,以便可以将其存储为变量并对此进行一些处理。我该怎么做 ?
stack1

2
状态。成功吗?在ruby 2.4上不再为我工作,它更改为status.success?:)
DanielG

14

有几种方法可以在Ruby中运行系统命令。

irb(main):003:0> `date /t` # surround with backticks
=> "Thu 07/01/2010 \n"
irb(main):004:0> system("date /t") # system command (returns true/false)
Thu 07/01/2010
=> true
irb(main):005:0> %x{date /t} # %x{} wrapper
=> "Thu 07/01/2010 \n"

但是,如果您实际上需要使用命令的stdin / stdout执行输入和输出,则可能需要查看IO::popen专门提供该功能的方法。


如果您的应用只有标准配置,popen效果很好。如果您需要更多的互动,或者想要对stdout,stdin尤其是stderr做一些不同的事情,您还需要研究一下open3:ruby-doc.org/core/classes/Open3.html
Paul Rubel 2010年

7
 folder = "/"
 list_all_files = "ls -al #{folder}"
 output = `#{list_all_files}`
 puts output

2

是的,这当然是可行的,但是实现方法因所讨论的“命令行”程序是以“全屏”还是命令行模式运行而有所不同。为命令行编写的程序倾向于读取STDIN并写入STDOUT。可以使用标准的backticks方法和/或system / exec调用在Ruby中直接调用它们。

如果程序在“全屏”模式(如屏幕或vi)下运行,则方法必须不同。对于这样的程序,您应该寻找“期望”库的Ruby实现。这将使您可以编写脚本,以期望在屏幕上看到的内容以及在屏幕上看到这些特定字符串时发送的内容。

这不太可能是最好的方法,您可能应该查看要达到的目标并找到相关的库/ gem来做到这一点,而不是尝试使现有的全屏应用程序自动化。例如,“ 需要帮助Ruby中的串行端口通信 ”处理了串行端口通信,如果您要使用提到的特定程序来实现此目的,则可以使用拨号前兆。


Ruby使用其内置的Pty模块提供了一个Expect的简单版本。
Tin Man

0

“最常用的方法是使用Open3此处”是上述代码的代码编辑版本,并进行了一些更正:

require 'open3'
puts"Enter the command for execution"
some_command=gets
stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.success?
  puts stdout
else
  STDERR.puts "ERRRR"
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.