2016-11-10 66 views
4

找不到合適的標題,我不明白破折號/ bash中的行爲。也就是說,如果一個命令失敗,我使用set -e來救助,並且命令組來處理積極的結果。爲什麼不設置-e導致「false」失敗?假&&真'?

即。一般方案是:

[ ! wantcommand ] || command 

比表示命令只在需要時纔會執行,並且失敗會自動終止腳本。

可能有一些必要的後處理,在這種情況下,我用這個:

[ ! wantcommand ] || { command && postprocess; } 

這導致了一些奇怪的bughunting,因爲這不會殺殼,我不能讓背後的原因。我現在必須經歷一些shell代碼塊,但想了解原因。

來進行測試:

bash -c 'set -e; { false || false && echo "post" ; }; echo "ec $?"' 

或:

bash -c 'set -e; { set -e; false || false && echo "post" ; }; echo "ec $?"' 

注:我不要求修復,但主要爲什麼返回代碼爲1,但外殼不會退出

回答

11

set -e僅保留未檢查失敗。

當支部建在失敗(使用ifuntilwhile&&||),即故障檢查。

如果規範不是以這種方式編寫的,短路布爾操作不能有效地用於流量控制,因爲假分支總是會導致退出。


the specification引用,並強調說:

當此選項時,當任何命令失敗(任何的Consequences of Shell Errors或通過返回一個退出狀態列出的原因大於零),外殼應立即退出,彷彿被執行退出特殊的內置工具不帶任何參數,但下列情況除外:

  1. 任何個人COM的失敗多命令管道中的命令不應導致shell退出。只應考慮管道本身的故障。

  2. 的-e設定應執行whileuntilif,或elif保留字以下化合物列表時被忽略,管線開始與!保留字,或其它的AND-OR列表的任何命令比最後的

  3. 如果子shell命令以外的複合命令的退出狀態是失敗的結果,而-e被忽略,則-e不適用於此命令。

此要求適用於shell環境和每個子shell環境。例如,在:

set -e; (false; echo one) | cat; echo two 

false命令使子外殼退出而不執行echo one;但是,執行echo two是因爲管道(false; echo one) | cat的退出狀態爲零。

請注意,此規範已隨時間而改變;執行POSIX規範之前修訂版的shell可能並不完全符合此處引用的版本。


要在這裏注入一些意見 - 我強烈建議閱讀BashFAQ #105,並確保你完全理解使得使用set -e而不是手工實現明確的錯誤處理決定前,其中描述的所有行爲。 FVUE wiki進一步描述了在bash本地模式下的set -e與POSIX模式之間的行爲區別,其同樣應該被理解。

+0

是的,在我看來,明確的錯誤處理方式沒有那麼混亂,看起來很醜,但至少容易理解。不能說我完全理解了這種行爲,這對我來說似乎非常不直觀。稍後將通讀鏈接,謝謝 我誤解的部分原因似乎來自make中的腳本,如果ec!= 0總是會失敗,無論如何 –

相關問題