如何从Ruby程序内部调用shell命令?然后如何将这些命令的输出返回到Ruby中?
当前回答
你也可以使用反勾操作符('),类似于Perl:
directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory
如果你需要简单的东西,很方便。
你想要使用哪种方法取决于你想要完成什么;有关不同方法的更多细节,请查看文档。
其他回答
这个解释是基于我的一个朋友写的带注释的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
不要忘记使用spawn命令创建一个后台进程来执行指定的命令。你甚至可以使用Process类和返回的pid来等待它的完成:
pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid
pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid
文档说:这个方法类似于#system,但它不会等待命令完成。
上面的答案已经非常棒了,但是我真的很想分享下面的总结文章:“在Ruby中运行Shell命令的6种方法”
基本上,它告诉我们:
# exec内核:
exec 'echo "hello $HOSTNAME"'
System和$?:
system 'false'
puts $?
Backticks ():
today = `date`
IO # execlp:
IO.popen("date") { |f| puts f.gets }
Open3#popen3—stdlib:
require "open3"
stdin, stdout, stderr = Open3.popen3('dc')
Open4#popen4—一个宝石:
require "open4"
pid, stdin, stdout, stderr = Open4::popen4 "false" # => [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>]
我绝对不是Ruby专家,但我还是会试一试:
$ irb
system "echo Hi"
Hi
=> true
你还应该能够做以下事情:
cmd = 'ls'
system(cmd)
在这些机制之间进行选择时需要考虑的一些事情是:
你只是想要stdout还是 也需要stderr ?甚至 分离出来吗? 你的产出有多大?你想要 将整个结果保存在内存中? 你想读一些你的吗 在子进程静止时输出 跑步吗? 你需要结果代码吗? 你需要一个Ruby对象吗 表示流程并允许您 按需杀死它?
您可能需要简单的反撇号(' ')、system()和IO。popen到成熟的Kernel.fork/Kernel。执行IO。pipe和IO.select。
如果子进程执行时间过长,您可能还想在混合过程中加入超时。
不幸的是,这在很大程度上取决于情况。
推荐文章
- 是否可以在MiniTest中运行单个测试?
- 如何在Ruby中生成a和b之间的随机数?
- 查看PS命令的全部输出
- 确保一次只运行一个shell脚本实例的快速方法
- 无法安装gem -未能建立gem本地扩展-无法加载这样的文件——mkmf (LoadError)
- 如何在Ruby中创建文件
- 什么是Ruby文件。开放模式和选项?
- Ruby数组到字符串的转换
- 如何分割(块)一个Ruby数组成X元素的部分?
- Ruby中“or”和||的区别?
- Git与Mercurial仓库的互操作性
- 如何测试参数是否存在在轨道
- 如何在Makefile中设置子进程的环境变量
- 如何让“wc -l”打印没有文件名的行数?
- 有效地测试Linux上的端口是否打开?