我们时常会与操作系统交互或在 Ruby 中执行 Shell 命令。Ruby为我们提供了完成该任务的诸多方法。

  1. Exec

    Kernel#exec 通过执行给定的命令来替换当前进程,例如:

    $ irb
    >> exec 'echo "hello $HOSTNAME"'
    hello codefun
    $

    注意 exec 利用 echo 命令替换了 irb 进程,然后退出。因为 Ruby 实际上结束了该方法,所以只能有限使用。该方法的缺点是,你无法从 Ruby 脚本中知道命令是执行成功还是失败。

  2. System

    system 命令与 exec 操作相似,但它是在 subshell 中执行,而不是替换当前进程。与 exec 相比,system 给我们更多的信息。如果命令执行成功,它返回 true;否则返回 false。

    $irb
    >> system 'echo "hello $HOSTNAME"'
    hello codefun
    => true
    >> system 'false'
    => false
    >> puts $?
    256
    => nil
    >>

    system 将进程的退出状态设置到全局变量 $?。注意 false 命令的退出状态,总是非 0 值。检查退出码让我们既可以抛出(raise)异常,又能够重试(retry)命令。

    新手注意:Unix 命令执行成功退出码为 0,否则为非 0。

    如果我们想知道“命令是否执行成功呢?”,使用 system 就很好。然而,我们时常想要捕获命令的输出,并在程序中使用。

  3. Backticks (`)

    backticks(也叫“backquotes”)在 subshell 中执行命令,并从该命令返回标准输出。

    $ irb
    >> today = `date`
    => "Wed Jul 4 22:03:15 CST 2012\n"
    >> $?
    => #<Process::Status: pid 6169 exit 0>
    >> $?.to_i
    => 0

    这也许是在 subshell 中执行命令最广为人知的方法。如你所见,它返回了命令的输出,然后我们可以像其他字符串一样使用它。

    注意 $? 并非是返回状态的整数,而实际是 Process::Status 对象。我们不仅得到了退出状态,而且有进程 ID。Process::Status#to_i 返回整数型的退出状态(#to_s 返回字符串型的退出状态)。

    使用 backticks 我们只能获得命令的标准输出(stdout),而不能获得其标准错 误(stderr)。在下面的例子中,我们执行 Perl 脚本来输出字符串到标准错误。

    $ irb
    >> warning = `perl -e "warn 'dust in the wind'"`
    dust in the wind at -e line 1.
    => ""
    >> puts warning => nil

    注意变量 warning 没有被设置。当我们在 Perl 中执行 warn
    时,产生的标准错误输出并没有被 backticks 捕获。

  4. IO#popen

    IO#popen 是在子进程中执行命令的另一种方法。popen 给你更多的控制,子进程的标准输入和标准输出都会连接到 IO 对象。

    $ irb
    >> IO.popen("date") { |f| puts f.gets }
    Wed Jul 4 22:02:31 CST 2012
    => nil

    虽然 IO#popen 不错,但是当需要这类细分层次的信息时,我通常使用Open3#popen3

  5. Open3#popen3

    Ruby 标准库包含 Open3 类。它易用,并能返回标准输入、标准输出、以及标准 错误。在本例中,让我们使用交互命令 dc。dc 是从标准输入读取的逆波计算器(reverse-polish calculator)。我们先 push 两个数字和一个操作符到堆栈 中。然后我们使用 p 来打印输出结果。下面我们 push 5、10 及 +,结果标准输出获得了15。

    $ irb
    >> require 'open3'
    => true
    >> stdin, stdout, stderr = Open3.popen3('dc')
    => [#<IO:fd 6>, #<IO:fd 7>, #<IO:fd 9>, #<Thread:0x816d46c sleep>]
    >> stdin.puts(5)
    => nil
    >> stdin.puts(10)
    => nil
    >> stdin.puts("+")
    => nil
    >> stdin.puts("p")
    => nil
    >> stdout.gets
    => "15\n"

    使用该命令我们不仅可以读取命令的输出,而且也能写到命令的标准输入。这允 许我们灵活地处理与命令的交互。

    如果我们需要,popen3 也将给我们标准错误。

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

    使用popen3 的缺点是 $? 不返回适当的退出状态。

    $ irb
    >> require 'open3'
    => true
    >> stdin, stdout, stderr = Open3.popen3('false')
    => [#<IO:fd 8>, #<IO:fd 10>, #<IO:fd 12>, #<Thread:0x8297644 sleep>]
    >> $?
    => nil
    >> $?.to_i
    => 0

    0?false 是假定返回非 0 退出状态。该缺点带我们到 Open4。

  6. Open4#popen4

    Open4#popen4 是 Ara Howard 创建的 Ruby Gem。它的操作与 open3 相似,例外是我们能从程序获得退出状态。popen4 为 subshell 返回进程 ID,这样我们能从等候的进程获得退出状态。(你需要安装 open4 gem)

    $ irb
    >> require 'open4'
    => true
    >> pid, stdin, stdout, stderr = Open4::popen4 "false"
    => [17913, #<IO:fd 6>, #<IO:fd 7>, #<IO:fd 9>]
    >> $?
    => nil
    >> pid
    => 17913
    >> ignored, status = Process::waitpid2 pid
    => [17913, #<Process::Status: pid 17913 exit 1>]
    >> status.to_i
    => 256

    你也可以作为块来调用 popen4,它将自动等候退出状态。

    $ irb
    >> require 'open4'
    => true
    >> status = Open4::popen4("false") do |pid, stdin, stdout, stderr|
    ?> puts "PID #{pid}"
    >> end
    PID 18535
    => #<Process::Status: pid 18535 exit 1>
    >> puts status
    pid 18535 exit 1
    => nil

原文来自 tech.natemurray.com
翻译 dailyrb
许可 CC-by-sa

在 Ruby 中执行 Shell 命令的 6 种方法的更多相关文章

  1. python中执行shell命令的几个方法小结(转载)

    转载:http://www.jb51.net/article/55327.htm python中执行shell命令的几个方法小结 投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014- ...

  2. python中执行shell命令的几个方法小结

    原文 http://www.jb51.net/article/55327.htm 最近有个需求就是页面上执行shell命令,第一想到的就是os.system, os.system('cat /proc ...

  3. 每天一个linux命令(62):sh命令 /Linux中执行shell脚本的4种方法总结

    bash shell 脚本的方法有多种,现在作个小结.假设我们编写好的shell脚本的文件名为hello.sh,文件位置在/data/shell目录中并已有执行权限. 方法一:切换到shell脚本所在 ...

  4. linux中执行shell命令的几种常用方法

    1 切换到shell脚本所在目录执行shell脚本: cd /test/shell ./test.sh 2 以绝对路径的方式执行shell脚本: /test/shell/test.sh 3 直接使用b ...

  5. Linux中执行shell脚本的4种方法总结

    bash shell 脚本的方法有多种,现在作个小结.假设我们编写好的shell脚本的文件名为hello.sh,文件位置在/data/shell目录中并已有执行权限. 方法一:切换到shell脚本所在 ...

  6. Linux中执行shell脚本的4种方法

    bash shell 脚本的方法有多种,现在作个小结.假设我们编写好的shell脚本的文件名为hello.sh,文件位置在/data/shell目录中并已有执行权限. 方法一:切换到shell脚本所在 ...

  7. python中执行shell命令的几个方法

    1.os.system() a=os.system("df -hT | awk 'NR==3{print $(NF-1)}'") 该命令会在页面上打印输出结果,但变量不会保留结果, ...

  8. vim中执行shell命令小结

    vim中执行shell命令,有以下几种形式 1):!command 不退出vim,并执行shell命令command,将命令输出显示在vim的命令区域,不会改变当前编辑的文件的内容 例如:!ls -l ...

  9. Python中执行系统命令常见的几种方法--转载

    Python中执行系统命令常见的几种方法 Python中执行系统命令常见的几种方法有: (1)os.system # 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息 # 如果再命令行下执 ...

随机推荐

  1. [置顶] HashTable vs HashMap

    转载请注明出处:http://blog.csdn.net/crazy1235/article/details/76686891 HashTable vs HashMap 构造函数 hash函数 syn ...

  2. Oozie_01安装教程【20161116】

    说明:hadoop用的是hadoop-2.5.0-cdh5.3.6 Oozie用的是oozie-4.0.0-cdh5.3.6 该测试环境用户名为hadoop  主机名为hadoop01 2.4安装部署 ...

  3. 各种Java加密算法

    如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorit ...

  4. 20145237 Exp9 Web安全基础实践

    基础问题回答 SQL注入攻击原理,如何防御: 部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,黑客利用这个bug在数据输入区恶意填入脚本,当数据被传回后台,黑客所填入的脚本语句被运行, ...

  5. jenkins配置email

    # 系统设置 # Jenkins Location # 邮件通知 # 高级 # Failed to send out e-mail 勾选“使用SSL协议” SMTP端口改为465 密码使用授权码,不能 ...

  6. streamsets 错误记录处理

    我们可以在stage 级别,或者piepline 级别进行error 处理配置 pipeline的错误记录处理 discard(丢踢) send response to Origin pipeline ...

  7. linux shell获取用户输入

    一.获取用户输入1.基本读取read命令接收标准输入的输入,或其它文件描述符的输入.得到输入后,read命令将数据输入放入一个标准变量中.[root@rac2 ~]# cat t8.sh #!/bin ...

  8. 【android】SDK环境变量配置

    Android SDK: Android SDK提供了你的API库和开发工具构建,测试和调试应用程序,Android.简单来讲,Android SDK 可以看做用于开发和运行Android应用的一个软 ...

  9. Accessing data in Hadoop using dplyr and SQL

    If your primary objective is to query your data in Hadoop to browse, manipulate, and extract it into ...

  10. 收藏的一些github开源项目,在这里记录一下

    1.在windows系统上在命令行中执行rm -fr */*.file 会报错, rimraf这个项目提供了跨平台支持rm命令,github地址: https://github.com/isaacs/ ...