`

Ruby执行shell命令的六种方法

阅读更多

Ruby执行shell命令的六种方法

NOV 18TH, 2014

在Ruby中,执行shell命令是一件不奇怪的事情,Ruby提供了大概6种方法供开发者进行实现。这些方法都很简单,本文将具体介绍一下如何在Ruby脚本中进行调用终端命令。

exec

exec会将指定的命令替换掉当前进程中的操作,指定命令结束后,进程结束。

1
2
exec 'echo "hello world"'
print 'abc'

执行上述的命令,结果如下,我们可以看到没有abc的输出,可以看出来,在执行echo "hello world"命令后进程就结束了。不会继续执行后面的print 'abc'

1
2
ruby testCommand.rb
hello world

使用exec一个头疼的事情就是没有办法知道shell命令执行成功还是失败。

system

system和exec相似,但是system执行的命令不会是在当前进程,而是在一个新创建的进程。system会返回布尔值来表明命令执行结果是成功还是失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ irb
> system 'echo "hello $HOSTNAME"'
hello androidyue
 => true
> puts $?
pid 11845 exit 0
 => nil
> system 'false'
 => false
> puts $?
pid 11858 exit 1
 => nil
>>

system会将进程的退出的状态码赋值给$?,如果程序正常退出,$?的值为0,否则为非0。通过检测退出的状态码我们可以在ruby脚本中抛出异常或者进行重试操作。

注:在Unix-like系统中进程的退出状态码以0和非0表示,0代表成功,非0代表失败。

system可以告诉我们命令执行是成功还是失败,但是有些时候我们需要得到执行命令的输出,并在脚本中使用。显然system无法直接满足,需要我们使用反引号来实现。

反引号(`)

使用反引号是shell中常用的获取命令输出内容的方法,在ruby中也是可以,而且一点都需要做改变。使用反引号执行命令也会将命令在另一个进程中执行。

1
2
3
4
5
6
7
1.9.3p448 :013 > today = `date`
 => "Sat Nov 15 19:28:55 CST 2014\n"
1.9.3p448 :014 > $?
 => #<Process::Status: pid 11925 exit 0> 
1.9.3p448 :015 > $?.to_i
 => 0
1.9.3p448 :016 >

上面的方法如此简单,我们可以直接对返回的字符串结果进行操作。

注意,$?已经不再是上述的那样单纯的退出状态码了,它实际上是一个Process::Status对象。我们从中不仅可以知道进程的退出状态码也可以知道进程的ID。使用$?.to_i会得到退出的状态码,使用$?.to_s会得到包含了进程id,退出状态码等信息的字符串。

使用反引号的一个结果就是我们只能得到标准的输出(stdout)而不能得到标准的错误信息(stderr),比如下面的例子,我们执行一个输出错误字符串的perl脚本。

1
2
3
4
5
6
7
  $ irb
  >> warning = `perl -e "warn 'dust in the wind'"`
  dust in the wind at -e line 1.
  => ""
  >> puts warning
  => nil

可以看出,warning并没有得到出错的信息,这就表明反引号无法得到标准错误的信息。

IO#popen

IO#popen也是一种执行命令的方法,其命令也是在另外的进程中执行。使用popen你可以像操作IO对象一样处理标准输入和输出。

1
2
3
4
$ irb
>> IO.popen("date") { |f| puts f.gets }
Mon Mar 12 18:58:56 PDT 2007
=> nil

Open3#popen3

在标准的Ruby库中还提供了一个Open3。使用这个类我们可以很容易的对标准输入,输出,错误进行处理。这里我们使用一个可以交互的工具dc。dc是一种逆波兰表达式(又叫做后缀表达式,每一运算符都置于其运算对象之后)的计算器,支持从标准输入读取数学表达式。在这个例子中,我们将两个数值和一个操作符进行压栈处理。然后使用p来输出结果。比如我们输入5和10,然后输入+,然后会得到15\n的输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
  $ irb
  >> stdin, stdout, stderr = Open3.popen3('dc')
  => [#<IO:0x6e5474>, #<IO:0x6e5438>, #<IO:0x6e53d4>]
  >> stdin.puts(5)
  => nil
  >> stdin.puts(10)
  => nil
  >> stdin.puts("+")
  => nil
  >> stdin.puts("p")
  => nil
  >> stdout.gets
  => "15\n"

使用这个方法,我们不仅可以读取到命令的输出还可以对命令进行输入操作。这个方法对于进行交互操作很方便。通过popen3,我们还可以得到标准的错误信息。

1
2
3
4
5
  # (irb continued...)
  >> stdin.puts("asdfasdfasdfasdf")
  => nil
  >> stderr.gets
  => "dc: stack empty\n"

但是,在ruby 1.8.5中popen3有一个缺陷,进程的退出状态没有写入到$?中。

1
2
3
4
5
6
7
8
9
  $ irb
  >> require "open3"
  => true
  >> stdin, stdout, stderr = Open3.popen3('false')
  => [#<IO:0x6f39c0>, #<IO:0x6f3984>, #<IO:0x6f3920>]
  >> $?
  => #<Process::Status: pid=26285,exited(0)>
  >> $?.to_i
  => 0

为什么是0,false命令执行后的退出状态应该是非0才对,由于这个缺陷,我们需要了解一下Open4

Open4#popen4

Open4#popen4使用起来和Open3#popen3差不多,而且我们也可以得到程序的退出状态。popen4还可以返回一个子进程ID。你也可以通过Process::waitpid2 加上对应的进程ID获得进程退出状态。但是前提是要安装open4的gem。

1
2
3
4
5
6
7
8
9
10
11
12
13
  $ irb
  >> require "open4"
  => true
  >> pid, stdin, stdout, stderr = Open4::popen4 "false"
  => [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>]
  >> $?
  => nil
  >> pid
  => 26327
  >> ignored, status = Process::waitpid2 pid
  => [26327, #<Process::Status: pid=26327,exited(1)>]
  >> status.to_i
  => 256

原文

分享到:
评论

相关推荐

    Ruby中执行Linux shell命令的六种方法详解

    system方法创建一个新的子进程来执行shell命令,它会返回一个布尔值,表示命令是否成功执行。如果命令执行成功,返回true;否则返回false。此外,可以使用`$?`变量获取进程的退出状态码,以便判断命令执行的结果。...

    Ruby中调用执行shell命令的6种方法

    碰到需要调用操作系统shell命令的时候,Ruby为我们提供了六种完成任务的方法: 1.Exec方法: Kernel#exec方法通过调用指定的命令取代当前进程例子: 代码如下:  $ irb  &gt;&gt; exec ‘echo “hello $HOSTNAME”‘  ...

    Ruby和Shell脚本实现判断成绩及格功能

    另一种方法是使用`case`语句,这在Shell脚本中相对复杂一些。`case`语句使用模式匹配,这里的模式是分数的字符串表示。由于Shell的限制,我们不能直接用范围来匹配,因此需要分别列出每个分数段。例如,`[0-9]`匹配...

    Alexa网络信息服务_Ruby_Shell_下载.zip

    2. **Shell脚本**:在Ruby中,可以使用`sh`或者`system`等方法来执行Shell命令,这使得Ruby成为编写系统管理脚本的有效工具。 3. **Alexa API**:如果项目是围绕Alexa网络信息服务,那么开发者可能使用了Alexa的API...

    一个示例警报repo,用于airbnbinterferon。_Ruby_Shell_.zip

    Ruby Shell通常指的是在Ruby环境中执行系统命令的工具,如`system`, `exec`等方法,或者是像`thor`这样的命令行工具库,它们允许开发者创建命令行界面来操作和交互与系统。 在压缩包文件名称列表中,我们只看到了...

    分钟教你shell脚本入门PPT课件.pptx

    编译型语言例如 C/C++/java,执行前需要将源代码转换成目标代码,而脚本编程语言例如 awk、perl、python、javascript、Ruby 和 shell,执行时需要解释器将代码转换成内部形式。 编译型语言的优点是效率高,但缺点是...

    shell+ruby.zip

    首先,`RedisStatusExporteryh.rb`可能是用Ruby编写的脚本,它的主要任务是连接到Redis服务器,执行Keyspace扫描(可能使用`KEYS`或`SCAN`命令,考虑到性能问题,更倾向于使用非阻塞的`SCAN`),筛选出匹配前缀的Key...

    用于检查应用程序健康状况的简单Rack中间件 -Ruby-Shell-下载

    健康检查的实现可能包括调用`system`或`spawn`函数来执行Shell命令,或者使用特定的Ruby库来检查特定的服务状态,如`pg`库检查PostgreSQL数据库,`net/http`库检查网络连接。 总的来说,这个Rack中间件是用Ruby编写...

    推荐系统的协同过滤_Ruby_Shell_下载.zip

    例如,脚本可能包含了下载资源、安装依赖、运行Ruby程序等命令。 推荐系统协同过滤的实现通常包括以下几个步骤: 1. 数据预处理:收集用户行为数据,如评分、点击、购买记录等,转化为适合算法处理的格式。 2. 计算...

    ruby解释性脚本语言中文文档

    Ruby是一种解释性的、面向对象的脚本语言,它以其简洁、优雅的语法和强大的功能而闻名。Ruby的设计理念强调程序员的生产力和代码的可读性,使得开发过程快速且反馈及时,非常适合进行快速原型开发和迭代。 在Ruby中...

    Ruby-Cocaine用于在Ruby代码中执行命令行的库

    这个库使得开发者可以更加方便、简洁地处理系统级别的交互,比如运行shell命令或者与外部系统进行通信。Cocaine库的主要目标是简化命令行接口(CLI)的调用,使代码更加模块化,易于理解和维护。 Cocaine库的核心...

    ruby - ruby tutorial

    IRb(Interactive Ruby Shell)是 Ruby 的交互式 shell,允许开发者在命令行中直接执行 Ruby 代码。这对于调试和测试小段代码非常有用。 启动 IRb 的方法很简单,只需在终端或命令提示符中键入 `irb` 即可。例如: ...

    Ruby-rubybuild编译和安装Ruby

    Ruby是一种动态、开源的编程语言,以其简洁、优雅的语法和强大的元编程能力著称。在Ruby开发中,为了管理不同版本的Ruby环境,我们常常会使用到`rbenv`和`ruby-build`这两个工具。本文将详细介绍如何使用`ruby-build...

    Shell 入门实战到精通

    本文详细介绍了 Shell 编程语⾔、Shell 脚本常⽤命令、Shell 正则表达式、Shell 编程、Shell 变量、Shell 数组、Shell 进阶实战和 Shell 案例实战等知识点,为读者提供了一个系统的 Shell 编程指南。

    ruby在unbuntu的安装版本

    Ruby是一种强大的、面向对象的脚本语言,尤其适合Web开发,如使用Rails框架。在Ubuntu操作系统上安装Ruby,可以让你利用其丰富的库和工具来构建高效的应用程序。本指南将详细讲解如何在Ubuntu系统上安装Ruby 2.1.5这...

    Ruby自学笔记

    使用%w和%W可以创建单引号或双引号的字符串数组,%r用于创建正则表达式模式,%x用于执行Shell命令,%i用于创建符号数组。字符串还可以通过heredoc语法构建多行字符串,可以使用多个边界字符串来标识字符串的开始和...

    绿化ruby193

    Ruby是一种面向对象的脚本语言,由日本人松本行弘(Yukihiro Matsumoto)于1995年设计并开发。它强调简洁性、可读性和开发效率,深受开发者喜爱。Ruby193是Ruby的一个特定版本,发布于2011年,包含了众多改进和优化。 ...

Global site tag (gtag.js) - Google Analytics