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


#1楼

上面的答案已经很不错了,但是我真的很想分享以下摘要文章:“ 在Ruby中运行Shell命令的6种方法 ”

基本上,它告诉我们:

Kernel#exec

exec 'echo "hello $HOSTNAME"'

system$?

system 'false'
puts $?

反引号(`):

today = `date`

IO#popen

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>]

#2楼

我绝对不是Ruby专家,但我会给您一个机会:

$ irb
system "echo Hi"
Hi
=> true

您还应该能够执行以下操作:

cmd = 'ls'
system(cmd)

#3楼

您还可以使用反引号运算符(`),类似于Perl:

directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory

如果您需要简单的东西,则非常方便。

您要使用哪种方法取决于您要完成的工作。 检查文档以获取有关不同方法的更多详细信息。


#4楼

我喜欢这样做的方法是使用%x文字,这使得在命令中使用引号变得容易(且易于阅读!),如下所示:

directorylist = %x[find . -name '*test.rb' | sort]

在这种情况下,它将用当前目录下的所有测试文件填充文件列表,您可以按预期进行处理:

directorylist.each do |filename|filename.chomp!# work with file
end

#5楼

该说明基于我的一个朋友的注释Ruby脚本 。 如果要改进脚本,请随时在链接上进行更新。

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

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

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#` ,通常称为反引号– `cmd`

    就像许多其他语言一样,包括Bash,PHP和Perl。

    返回shell命令的结果(即标准输出)。

    文件: http : //ruby-doc.org/core/Kernel.html#method-i-60

     value = `echo 'hi'` value = `#{cmd}` 
  2. 内置语法%x( cmd )

    x字符后是分隔符,可以是任何字符。 如果定界符是字符([{< ,下次出现分隔符时,允许使用字符串插值#{ ... }

    像反引号一样,返回shell命令的结果(即标准输出)。

    文件: http : //www.ruby-doc.org/docs/ProgrammingRuby/html/language.html

     value = %x( echo 'hi' ) value = %x[ #{cmd} ] 
  3. Kernel#system

    在子shell中执行给定命令。

    如果找到命令并成功运行,则返回true ,否则返回false

    文件: http : //ruby-doc.org/core/Kernel.html#method-i-system

     wasGood = system( "echo 'hi'" ) wasGood = system( cmd ) 
  4. Kernel#exec

    通过运行给定的外部命令来替换当前进程。

    不返回任何值,当前进程将被替换且永远不会继续。

    文件: 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{} ,则访问上次系统执行的命令的状态。 然后,您可以访问exitstatuspid属性:

$?.exitstatus

有关更多阅读,请参阅:

  • http://www.elctech.com/blog/im-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

#6楼

这是我在OS X上的ruby脚本中使用的一个很酷的脚本(以便即使从窗口切换后也可以启动脚本并获得更新):

cmd = %Q|osascript -e 'display notification "Server was reset" with title "Posted Update"'|
system ( cmd )

#7楼

另一种选择:

当你:

  • 需要stderr以及stdout
  • 无法/不会使用Open3 / Open4(它们在Mac上的NetBeans中抛出异常,不知道为什么)

您可以使用外壳重定向:

puts %x[cat bogus.txt].inspect=> ""puts %x[cat bogus.txt 2>&1].inspect=> "cat: bogus.txt: No such file or directory\n"

自MS-DOS成立以来, 2>&1语法可在Linux ,Mac和Windows上运行。


#8楼

不要忘记使用spawn命令创建后台进程来执行指定的命令。 您甚至可以使用Process类和返回的pid等待其完成:

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pidpid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

该文档说:此方法与#system类似,但它不等待命令完成。


#9楼

如果您的案例比普通案例更为复杂(无法通过`` )处理,请在此处签出Kernel.spawn() 。 这似乎是普通Ruby提供的用于执行外部命令的最通用/最全面的功能。

例如,您可以使用它来:

  • 创建进程组(Windows)
  • 将错误重定向到文件或其他文件。
  • 设置环境变量,umask
  • 在执行命令之前更改目录
  • 设置CPU /数据/资源限制
  • 用其他答案中的其他选项来完成所有事情,但是要编写更多代码。

官方的红宝石文档有足够好的例子。

env: hashname => val : set the environment variablename => nil : unset the environment variable
command...:commandline                 : command line string which is passed to the standard shellcmdname, arg1, ...          : command name and one or more arguments (no shell)[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hashclearing environment variables::unsetenv_others => true   : clear environment variables except specified by env:unsetenv_others => false  : dont clear (default)process group::pgroup => true or 0 : make a new process group:pgroup => pgid      : join to specified process group:pgroup => nil       : dont change the process group (default)create new process group: Windows only:new_pgroup => true  : the new process is the root process of a new process group:new_pgroup => false : dont create a new process group (default)resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.:rlimit_resourcename => limit:rlimit_resourcename => [cur_limit, max_limit]current directory::chdir => strumask::umask => intredirection:key:FD              : single file descriptor in child process[FD, FD, ...]   : multiple file descriptor in child processvalue:FD                        : redirect to the file descriptor in parent processstring                    : redirect to file with open(string, "r" or "w")[string]                  : redirect to file with open(string, File::RDONLY)[string, open_mode]       : redirect to file with open(string, open_mode, 0644)[string, open_mode, perm] : redirect to file with open(string, open_mode, perm)[:child, FD]              : redirect to the redirected file descriptor:close                    : close the file descriptor in child processFD is one of follows:in     : the file descriptor 0 which is the standard input:out    : the file descriptor 1 which is the standard output:err    : the file descriptor 2 which is the standard errorinteger : the file descriptor of specified the integerio      : the file descriptor specified as io.filenofile descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not:close_others => false : inherit fds (default for system and exec):close_others => true  : dont inherit (default for spawn and IO.popen)

#10楼

这是基于“ 何时使用在Ruby中启动子流程的每种方法 ”的流程图。 另请参见“ 欺骗应用程序以使其标准输出是终端而不是管道 ”。


#11楼

我认为这是关于在Ruby中运行Shell脚本的最佳文章:“在Ruby 中运行Shell命令的6种方法 ”。

如果只需要获取输出,请使用反引号。

我需要更高级的东西,例如STDOUT和STDERR,所以我使用了Open4 gem。 您已在此处说明了所有方法。


#12楼

  • backticks`方法是从ruby调用shell命令的最简单方法。 它返回shell命令的结果。

      url_request = 'http://google.com' result_of_shell_command = `curl #{url_request}` 

#13楼

最简单的方法是,例如:

reboot = `init 6`
puts reboot

#14楼

在这些机制之间进行选择时,需要考虑以下几点:

  1. 您只是想要stdout还是需要stderr? 甚至分开?
  2. 您的输出多少? 您是否要将整个结果保存在内存中?
  3. 您是否想在子进程仍在运行时读取一些输出?
  4. 您需要结果代码吗?
  5. 您是否需要一个代表过程的红宝石对象,并允许您按需将其杀死?

您可能需要从简单的反引号什么(``),系统(),并IO.popen到成熟Kernel.fork / Kernel.execIO.pipeIO.select

如果子流程执行时间过长,您可能还想将超时投入混合。

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


#15楼

如果您确实需要Bash,请按照“最佳”答案中的注释进行操作。

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

如果需要使用Bash, bash -c "your Bash-only command"在所需的调用方法中插入bash -c "your Bash-only command"

quick_output = system("ls -la")

quick_bash = system("bash -c 'ls -la'")

去测试:

system("echo $SHELL") system('bash -c "echo $SHELL"')

或者,如果您正在运行现有的脚本文件(例如script_output = system("./my_script.sh") ),Ruby 应该遵守shebang,但您始终可以使用system("bash ./my_script.sh")来确保(尽管/bin/sh运行/bin/bash可能会有一些开销,但您可能不会注意到。


#16楼

给定命令,例如attrib

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

我发现虽然此方法不如system(“ thecommand”)或反引号中的command令人难忘,但与其他方法相比,此方法的优点是..例如,反引号似乎并不会让我“放'我运行的命令/将要运行的命令存储在变量中,而system(“ thecommand”)似乎没有让我获取输出。 尽管此方法使我可以同时执行上述两项操作,但可以让我独立访问stdin,stdout和stderr。

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

http://ruby-doc.org/stdlib-2.4.1/libdoc/open3/rdoc/Open3.html


#17楼

这并不是一个真正的答案,但也许有人会发现它有用,并且与此有关。

在Windows上使用TK GUI时,您需要从rubyw调用shell命令,您总是会弹出一个烦人的cmd窗口,时间不到一秒钟。

为了避免这种情况,您可以使用

WIN32OLE.new('Shell.Application').ShellExecute('ipconfig > log.txt','','','open',0)

要么

WIN32OLE.new('WScript.Shell').Run('ipconfig > log.txt',0,0)

两者都将ipconfig的输出存储在'log.txt'中,但是不会出现任何窗口。

require 'win32ole'在脚本中require 'win32ole'

使用TK和rubyw时, system()exec()spawn()都会弹出该烦人的窗口。


#18楼

我们可以通过多种方式实现它。

使用Kernel#exec ,执行此命令后不执行任何操作:

exec('ls ~')

使用backticks or %x

`ls ~`
=> "Applications\nDesktop\nDocuments"
%x(ls ~)
=> "Applications\nDesktop\nDocuments"

使用Kernel#system命令,如果成功,则返回true ;如果失败,则返回false如果命令执行失败,则返回nil

system('ls ~')
=> true

#19楼

使用此处的答案并链接到Mihai的答案中,我组成了一个满足这些要求的函数:

  1. 整齐地捕获STDOUT和STDERR,以便从控制台运行我的脚本时它们不会“泄漏”。
  2. 允许将参数作为数组传递给外壳,因此无需担心转义。
  3. 捕获命令的退出状态,以便在发生错误时可以将其清除。

另外,如果shell命令成功退出(0)并将任何内容放入STDOUT,则此命令也将返回STDOUT。 以这种方式,它不同于system ,在这种情况下, system仅返回true

代码如下。 具体功能是system_quietly

require 'open3'class ShellError < StandardError; end#actual function:
def system_quietly(*cmd)exit_status=nilerr=nilout=nilOpen3.popen3(*cmd) do |stdin, stdout, stderr, wait_thread|err = stderr.gets(nil)out = stdout.gets(nil)[stdin, stdout, stderr].each{|stream| stream.send('close')}exit_status = wait_thread.valueendif exit_status.to_i > 0err = err.chomp if errraise ShellError, errelsif outreturn out.chompelsereturn trueend
end#calling it:
beginputs system_quietly('which', 'ruby')
rescue ShellErrorabort "Looks like you don't have the `ruby` command. Odd."
end#output: => "/Users/me/.rvm/rubies/ruby-1.9.2-p136/bin/ruby"

#20楼

我最喜欢的是Open3

  require "open3"Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }

从Ruby调用Shell命令相关推荐

  1. Ruby调用shell命令

    原来发在diandian的几篇旧闻,也一并转到iteye上来吧. 1. exec exec 'echo "hello $HOSTNAME"' 用echo命令来取代当前进程,无法知道 ...

  2. python 调用shell命令的方法

    转载: https://www.cnblogs.com/thinker-lj/p/3860123.html https://www.cnblogs.com/wenwangt/p/4897961.htm ...

  3. python调用shell命令-Python调用shell命令常用方法(4种)

    方法一.使用os模块的system方法:os.system(cmd),其返回值是shell指令运行后返回的状态码,int类型,0表示shell指令成功执行,256表示未找到,该方法适用于shell命令 ...

  4. python调用shell命令-用Python调用Shell命令

    Python经常被称作"胶水语言",因为它能够轻易地操作其他程序,轻易地包装使用其他语言编写的库,也当然可以用Python调用Shell命令. 用Python调用Shell命令有如 ...

  5. python调用shell命令-在Python中执行shell命令的6种方法,你都知道吗?

    原标题:在Python中执行shell命令的6种方法,你都知道吗? Python经常被称作"胶水语言",因为它能够轻易地操作其他程序,轻易地包装使用其他语言编写的库.今天我们就讲解 ...

  6. python调用shell命令-「Python」6种python中执行shell命令方法

    用Python调用Shell命令有如下几种方式: 第一种: os.system("The command you want"). 这个调用相当直接,且是同步进行的,程序需要阻塞并等 ...

  7. Awk中调用shell命令

    Awk中调用shell命令 需求 在awk中,有时候需要调用linux系统中命令,如计算字符串的MD5值,并保存下来. 方法参考 call a shell command from inside aw ...

  8. python 中调用shell命令

    subprocess模块 根据Python官方文档说明,subprocess模块用于取代上面这些模块.有一个用Python实现的并行ssh工具-mssh,代码很简短,不过很有意思,它在线程中调用sub ...

  9. python使用shell命令_python 调用shell命令的方法

    在python程序中调用shell命令,是件很酷且常用的事情-- 1. os.system(command) 此函数会启动子进程,在子进程中执行command,并返回command命令执行完毕后的退出 ...

最新文章

  1. WordPress 性能优化:为什么我的博客比你的快
  2. 二叉树的定义、性质、存储
  3. 小学三年级上册计算机计划,小学三年级数学上册教学计划
  4. gradle下载及配置
  5. Adaline神经网络简单介绍和MATLAB简单实现
  6. Vue的computed(计算属性)使用实例之TodoList
  7. python虚拟机 基于寄存器_基于栈虚拟机和基于寄存器虚拟机的比较
  8. cgroup代码浅析(1)
  9. IC卡应用系统开发-(一)卡片读写
  10. cplex java_cplex-Java-样例代码解析
  11. 计算机英语CMYK全称,CMYK是什么意思 CMYK与RGB的区别介绍
  12. 搜索引擎算法之关键词类目预测
  13. Win10系统更新显卡驱动无限蓝屏重启-驱动人生解决方案
  14. 大学生发展规划与就业指导(三)万学网答案
  15. python上的包嗅探
  16. 图片太大上传不了怎么缩小?jpg图片压缩大小的方法
  17. TJOI2015 弦论
  18. 2019新征程 | SMIA新一批会员公示
  19. 3dmax2014【3dsmax2014】官方简体中文(64位)安装图文教程、破解注册方法
  20. android动态化ui框架,简单实用的Android UI微博动态点赞效果

热门文章

  1. 算法----合并两个有序链表
  2. android TextView 文本里面设置超链接
  3. 第七周项目一-成员函数、友元函数和一般函数有区别(1)
  4. Android之Android触摸事件传递机制
  5. 创建型模式--多例模式
  6. RxSwift技术路线与参考资料
  7. iOS架构-制作属于自己的cocoapods以及podspec文件讲解(20)
  8. [C++] stack和queue的常用函数
  9. Hibernate: Encountered a duplicated sql alias [] during auto-discovery of a native-sql
  10. JMeter Sampler之BeanShellSampler的使用