Ruby中執(zhí)行Linux shell命令的六種方法詳解
在Ruby中,執(zhí)行shell命令是一件不奇怪的事情,Ruby提供了大概6種方法供開發(fā)者進(jìn)行實(shí)現(xiàn)。這些方法都很簡單,本文將具體介紹一下如何在Ruby腳本中進(jìn)行調(diào)用終端命令。
exec
exec會(huì)將指定的命令替換掉當(dāng)前進(jìn)程中的操作,指定命令結(jié)束后,進(jìn)程結(jié)束。
exec 'echo "hello world"'
print 'abc'
執(zhí)行上述的命令,結(jié)果如下,我們可以看到?jīng)]有abc的輸出,可以看出來,在執(zhí)行echo "hello world"命令后進(jìn)程就結(jié)束了。不會(huì)繼續(xù)執(zhí)行后面的print 'abc'。
ruby testCommand.rb
hello world
使用exec一個(gè)頭疼的事情就是沒有辦法知道shell命令執(zhí)行成功還是失敗。
system
system和exec相似,但是system執(zhí)行的命令不會(huì)是在當(dāng)前進(jìn)程,而是在一個(gè)新創(chuàng)建的進(jìn)程。system會(huì)返回布爾值來表明命令執(zhí)行結(jié)果是成功還是失敗。
$ irb
> system 'echo "hello $HOSTNAME"'
hello androidyue
=> true
> puts $?
pid 11845 exit 0
=> nil
> system 'false'
=> false
> puts $?
pid 11858 exit 1
=> nil
>>
system會(huì)將進(jìn)程的退出的狀態(tài)碼賦值給$?,如果程序正常退出,$?的值為0,否則為非0。通過檢測退出的狀態(tài)碼我們可以在ruby腳本中拋出異?;蛘哌M(jìn)行重試操作。
注:在Unix-like系統(tǒng)中進(jìn)程的退出狀態(tài)碼以0和非0表示,0代表成功,非0代表失敗。
system可以告訴我們命令執(zhí)行是成功還是失敗,但是有些時(shí)候我們需要得到執(zhí)行命令的輸出,并在腳本中使用。顯然system無法直接滿足,需要我們使用反引號(hào)來實(shí)現(xiàn)。
反引號(hào)(`)
使用反引號(hào)是shell中常用的獲取命令輸出內(nèi)容的方法,在ruby中也是可以,而且一點(diǎn)都需要做改變。使用反引號(hào)執(zhí)行命令也會(huì)將命令在另一個(gè)進(jìn)程中執(zhí)行。
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 >
上面的方法如此簡單,我們可以直接對(duì)返回的字符串結(jié)果進(jìn)行操作。
注意,$?已經(jīng)不再是上述的那樣單純的退出狀態(tài)碼了,它實(shí)際上是一個(gè)Process::Status對(duì)象。我們從中不僅可以知道進(jìn)程的退出狀態(tài)碼也可以知道進(jìn)程的ID。使用$?.to_i會(huì)得到退出的狀態(tài)碼,使用$?.to_s會(huì)得到包含了進(jìn)程id,退出狀態(tài)碼等信息的字符串。
使用反引號(hào)的一個(gè)結(jié)果就是我們只能得到標(biāo)準(zhǔn)的輸出(stdout)而不能得到標(biāo)準(zhǔn)的錯(cuò)誤信息(stderr),比如下面的例子,我們執(zhí)行一個(gè)輸出錯(cuò)誤字符串的perl腳本。
$ irb
>> warning = `perl -e "warn 'dust in the wind'"`
dust in the wind at -e line 1.
=> ""
>> puts warning
=> nil
可以看出,warning并沒有得到出錯(cuò)的信息,這就表明反引號(hào)無法得到標(biāo)準(zhǔn)錯(cuò)誤的信息。
IO#popen
IO#popen也是一種執(zhí)行命令的方法,其命令也是在另外的進(jìn)程中執(zhí)行。使用popen你可以像操作IO對(duì)象一樣處理標(biāo)準(zhǔn)輸入和輸出。
$ irb
>> IO.popen("date") { |f| puts f.gets }
Mon Mar 12 18:58:56 PDT 2007
=> nil
Open3#popen3
在標(biāo)準(zhǔn)的Ruby庫中還提供了一個(gè)Open3。使用這個(gè)類我們可以很容易的對(duì)標(biāo)準(zhǔn)輸入,輸出,錯(cuò)誤進(jìn)行處理。這里我們使用一個(gè)可以交互的工具dc。dc是一種逆波蘭表達(dá)式(又叫做后綴表達(dá)式,每一運(yùn)算符都置于其運(yùn)算對(duì)象之后)的計(jì)算器,支持從標(biāo)準(zhǔn)輸入讀取數(shù)學(xué)表達(dá)式。在這個(gè)例子中,我們將兩個(gè)數(shù)值和一個(gè)操作符進(jìn)行壓棧處理。然后使用p來輸出結(jié)果。比如我們輸入5和10,然后輸入+,然后會(huì)得到15\n的輸出。
$ 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"
使用這個(gè)方法,我們不僅可以讀取到命令的輸出還可以對(duì)命令進(jìn)行輸入操作。這個(gè)方法對(duì)于進(jìn)行交互操作很方便。通過popen3,我們還可以得到標(biāo)準(zhǔn)的錯(cuò)誤信息。
# (irb continued...)
>> stdin.puts("asdfasdfasdfasdf")
=> nil
>> stderr.gets
=> "dc: stack empty\n"
但是,在ruby 1.8.5中popen3有一個(gè)缺陷,進(jìn)程的退出狀態(tài)沒有寫入到$?中。
$ 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命令執(zhí)行后的退出狀態(tài)應(yīng)該是非0才對(duì),由于這個(gè)缺陷,我們需要了解一下Open4
Open4#popen4
Open4#popen4使用起來和Open3#popen3差不多,而且我們也可以得到程序的退出狀態(tài)。popen4還可以返回一個(gè)子進(jìn)程ID。你也可以通過Process::waitpid2 加上對(duì)應(yīng)的進(jìn)程ID獲得進(jìn)程退出狀態(tài)。但是前提是要安裝open4的gem。
$ 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
相關(guān)文章
介紹Ruby中的模塊與混合類型的相關(guān)知識(shí)
這篇文章主要介紹了Ruby中的模塊與混合類型的相關(guān)知識(shí),包括平常人們常說的多態(tài)與繼承等相關(guān)知識(shí)點(diǎn),需要的朋友可以參考下2015-05-05Ruby on Rails實(shí)現(xiàn)最基本的用戶注冊(cè)和登錄功能的教程
這里我們主要以has_secure_password的用戶密碼驗(yàn)證功能為中心,來講解Ruby on Rails實(shí)現(xiàn)最基本的用戶注冊(cè)和登錄功能的教程,需要的朋友可以參考下2016-06-06使用Ruby來編寫訪問Twitter的命令行應(yīng)用程序的教程
這篇文章主要介紹了使用Ruby來編寫訪問Twitter的命令行應(yīng)用程序的教程,文章來自于IBM官方網(wǎng)站技術(shù)文檔,需要的朋友可以參考下2015-04-04ruby線程實(shí)現(xiàn)生產(chǎn)者消費(fèi)者問題示例(隊(duì)列Queue實(shí)現(xiàn)線程同步)
這篇文章主要介紹了ruby線程實(shí)現(xiàn)生產(chǎn)者消費(fèi)者問題示例(隊(duì)列Queue實(shí)現(xiàn)線程同步),需要的朋友可以參考下2014-05-05Ruby中實(shí)現(xiàn)把字符串轉(zhuǎn)換為類的2種方法
這篇文章主要介紹了Ruby中實(shí)現(xiàn)把字符串轉(zhuǎn)換為類的2種方法,其中一種是rails提供的方法,需要的朋友可以參考下2014-10-10