帶有 `set -e` 的 Bash 腳本不會在 `... && ...` 指令上停止

帶有 `set -e` 的 Bash 腳本不會在 `... && ...` 指令上停止

set -e習慣於出現第一個錯誤時停止 bash 腳本

一切正常,除非我使用以下命令&&

$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$

和....相比:

$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$

第一個範例仍然會回顯I'm running!,但第二個範例不會。為什麼他們的行為會不同?

UPD。類似問題:https://stackoverflow.com/questions/6930295/set-e-and-short-tests

答案1

這是有記錄的行為。這bash(1) 手冊頁說,對於set -e,

while如果失敗的命令是緊接在or關鍵字之後的命令清單的一部分,是緊接在或保留字 until之後的測試的一部分,則 shell 不會退出,ifelif&&||清單中執行的任何命令的一部分&&除了最後一個或 之後的命令||,管道中除最後一個命令之外的任何命令,或命令的返回值與!.
[強調。

還有POSIX外殼命令語言規格 確認這是正確的行為:

當執行、、或保留字之後的複合清單、以保留字開頭的管道或 AND-OR 清單中除最後一個命令之外的任何命令-e時,應忽略該設定。whileuntilifelif!

第2.9.3節清單該文件的定義

&&AND-OR 清單是由運算子「 」和「 」分隔的一個或多個管道的序列||

答案2

set -e選項在某些情況下不起作用,這是標準行為,並且可以跨 POSIX 相容 shell 移植。


失敗的命令是管道的一部分:

false | true; echo printed

將列印printed.

並且只考慮管道本身的故障:

true | false; echo 'not printed'

不會列印任何內容。


失敗的命令在whileuntilifelif保留字之後的複合列表中運行,以保留字開頭的管道,或者作為除最後一個之外的!一部分&&或列表的任何命令:||

false || true; echo printed

最後一個命令失敗仍然會受影響set -e

true && false; echo 'not printed'

子外殼複合命令失敗:

(false; echo 'not printed') | cat -; echo printed

答案3

我的猜測是 if-then 條件作為一個整體評估為 true。

我試過

set -e
if cd not_existing_dir
then  echo 123
fi
echo "I'm running! =P"

誰給

-bash: cd: not_existing_dir: No such file or directory
I'm running! =P

錯誤代碼被 if 條件捕獲,因此 bash 不會觸發執行結束。

相關內容