bash script 前面沒有特別設定的話,執行時遇到錯誤,通常會繼續往下執行,而不會像平常熟悉的程式語言遇到 exception 時(沒有 error handling)直接跳出結束執行。

另外,在開發、撰寫 bash script 時,也時常有需要 debug 的時候。

因此,以下簡單介紹一些常用且有幫助的 bash script 前置設定。

以下設定只在 bash 上測試過,其他 shell 不一定能使用。

set -x

在 bash script 開發過程中,如果需要 debug 可以在 script 前面加上 set -x。行為是 script 在執行時,執行每一行指令前,會先把指令印出來。

雖然不像一些高階程式語言有 debugger 能設中斷點、直接觀察變數值以及 stack 狀況,但對於有許多變數、迴圈、邏輯判斷的複雜 script 來說,透過 print-debug like 的方式來找碴也十分有幫助。

set -eou pipefail

bash script 執行時遇到錯誤,以及遇到 unset variable 時,預設不會中斷而是會繼續執行。面對這種狀況,能在 script 前加上 set -eou pipefail 解決以上問題。

Arguments

-e: 任何指令執行失敗會讓整個script跳出,return value非零。

-u: unset variables would exit the script.

-o pipefail: pipeline會把最後一個指令當作return value。

使用此option後只要pipeline中任一指令失敗就會回傳非零。

不過,要搭配-e才能避免失敗後繼續往下執行。

Test

-e:

#!/bin/bash

set -e      # 請自行移除觀察行為有何差別

ls not-exist
echo "HI"

加上 set -e 後就不會印出 HI,另外,echo $? 觀察 return value 也從 0 變成 1

-u:

#!/bin/bash

set -u      # 請自行移除觀察行為有何差別

echo "$notset"

加上 set -u 後第 5 行會報錯,另外,echo $? 觀察 return value 也從 0 變成 1

-o pipefail

#!/bin/bash

set -o pipefail     # 請自行移除觀察行為有何差別

ls not-exist | echo "HI"

加上 set -o pipefail依然會繼續執行 pipeline 剩餘指令,因此能看到 stdout 印出 HI。

原本 script 會把 pipeline 最後一個指令的 return 當作 return value,但加上此 option 後,只要 pipeline 中任何一個指令失敗,return

value 就是 1,因此觀察到 return value 從 0 變成 1。

#!/bin/bash

set -o pipefail     # 請自行移除觀察行為有何差別

echo "HI" | ls not-exist

這個範例無論有沒有加 set -o pipefail,return value 都是 1,原因與上面提到 pipeline 的 return value 機制有關。

範例 Example sciprt

#!/bin/bash

set -eou pipefail
set -x

# your script...

結語

之後有遇到其他好用的設定會再慢慢更新上來…