在 Ruby 中執行 Shell 命令的 6 種方法

來源:互聯網
上載者:User

標籤:http   io   ar   os   使用   sp   on   bs   ad   

我們時常會與作業系統互動或在 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}">> endPID 18535=> #<Process::Status: pid 18535 exit 1>>> puts statuspid 18535 exit 1=> nil

原文來自 tech.natemurray.com
翻譯 dailyrb
許可 CC-by-sa

在 Ruby 中執行 Shell 命令的 6 種方法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.