2010-02-08 44 views
4

我正在用Ruby編寫一些腳本,我需要通過shell命令與一些非Ruby代碼進行交互。我知道從Ruby執行shell命令至少有6 different ways,不幸的是,當shell命令失敗時,這些命令都不會停止執行。在shell命令失敗時引發異常?

基本上,我正在尋找的東西做等價的:

set -o errexit 

...在bash腳本。理想情況下,解決方案會在命令失敗時觸發異常(即通過檢查非零返回值),也可能將stderr作爲消息。這不會太難寫,但它似乎已經存在。有沒有我沒有找到的選項?

回答

7

最簡單的方式是創建一個新的功能(或重新定義現有的)來調用系統(),並檢查錯誤代碼。

喜歡的東西:

old_sys = system 

def system(...) 
    old_system(...) 
    if $? != 0 then raise :some_exception 
end 

這應該做你想要什麼。

+2

是的,當我說「不會太難寫」時,這就是我的想法,但它看起來應該已經解決了,你知道嗎?感謝這個例子。 – 2010-02-09 15:00:48

+1

雖然,你會想''提高'而不是'扔' – 2010-02-09 15:12:03

+0

@glenn好抓,固定。 – user269044 2010-02-09 15:16:46

6

你可以使用一個ruby的特殊變量。 $? (類似於相同的shell腳本var)。

`ls` 
if $?.to_s == "0" 
    # Ok to go 
else 
    # Not ok 
end 

幾乎每個程序都將此var設置爲0,如果一切正常。

+6

爲什麼你會使用'to_s'以字符串'0'比較? '如果$? == 0' – 2010-02-09 15:13:17

+0

我會說,即使'如果$?零?' – Nakilon 2016-05-12 19:03:56

+0

@Nakilon'''$?零?'''提高NoMethodError – 2017-06-14 02:28:23

6

點點簡單:你不需要檢查$?瓦特/ system,並且因爲該命令,你會跑去輸出到stderr本身通常可以只非零退出,而不是拋出一個異常瓦特/一個醜陋的堆棧-trace:

system("<command>") || exit(1) 

所以你可以採取更進了一步,做:

(system("<command 1>") && 
    system("<command 2>") && 
    system("<command 3>")) || exit(1) 

...這將短路和錯誤失敗(除了是難以閱讀)。

價:從紅寶石2.0 DOC爲system(儘管真正的1.8.7爲好):

系統返回true如果該命令給出零個退出狀態,false爲非零退出狀態。

http://www.ruby-doc.org/core-2.0.0/Kernel.html#method-i-system

+0

有趣,我喜歡這樣。你可以添加一個鏈接到你的參考(你發現這個的Ruby文檔的一部分)? – 2013-12-23 16:01:44