Shell Script 是什麼#
Shell Script 是將一連串的 Shell 指令寫在純文字檔案中,讓系統依序執行。它不需要編譯,直接由 Shell 直譯執行。你可以把它想成錄製巨集——將你在終端中手動輸入的操作自動化。
為什麼 Shell Script 重要#
- 系統管理自動化:開機服務、定期備份、日誌清理
- 批次操作:對大量檔案或目錄進行統一處理
- CI/CD Pipeline:幾乎所有的 CI/CD 系統底層都在跑 shell script
- 快速原型開發:不需要安裝任何開發環境,任何 Linux 系統都能跑
Shell Script 的優勢在於「黏合」——串接各種指令和工具。它不適合處理複雜的資料結構或高效能運算。當 script 超過幾百行或邏輯變得很複雜時,應考慮改用 Python、Go 等語言。
Script 的基本結構#
一個良好的 Shell Script 包含以下部分:
- Shebang 宣告:第一行的
#!/bin/bash,告訴系統用哪個 Shell 來執行 - 說明註解:腳本用途、作者、版本、修改記錄
- 環境變數設定:確保腳本在預期的環境中執行
- 主程式邏輯
- 回傳值:用
exit指定回傳碼
執行方式的差異#
Shell Script 的執行方式會影響變數的作用範圍:
- 直接執行(
./script.sh或bash script.sh):在子程序中執行,script 中設定的變數不會影響父程序 source script.sh:在目前的 Shell 中執行,變數會保留在目前環境中
這就是為什麼修改了
~/.bashrc後要執行source ~/.bashrc——你需要在目前的 Shell 中重新載入設定,而不是在子程序中執行它。
判斷式#
test 指令與 [ ]#
Shell 的判斷不是用 if (condition) 這種一般程式語言的語法,而是透過 test 指令或其等價的 [ ] 中括號語法。
判斷的類型:
- 檔案測試:檔案是否存在、是否為目錄、是否可讀寫執行
- 數值比較:
-eq、-ne、-gt、-lt、-ge、-le - 字串比較:
=、!=、-z(空字串)、-n(非空字串)
[ ]中括號內的每個元素必須用空格分隔,包括括號本身。[$var = "hello"]是錯誤的,正確寫法是[ "$var" = "hello" ]。變數也要用雙引號包裹,避免變數為空時造成語法錯誤。
預設變數#
Shell Script 接收參數的方式:
| 變數 | 意義 |
|---|---|
$0 | Script 本身的檔名 |
$1 ~ $N | 第 1 ~ 第 N 個參數 |
$# | 參數個數 |
$@ | 所有參數(各自獨立) |
$* | 所有參數(合為一個字串) |
條件判斷與流程控制#
if…then…fi#
基本的條件分支結構。elif 用於多重條件判斷。
case…esac#
類似其他語言的 switch-case,適合用在固定選項的判斷(如命令列選項的解析)。
function#
Shell Script 支援函式定義,用於模組化重複使用的邏輯。函式的參數同樣使用 $1、$2…,注意這些參數是函式的區域參數,不是 script 的全域參數。
迴圈#
while / until#
while:條件成立時持續執行until:條件不成立時持續執行(while 的相反)
for#
兩種形式:
- 清單式:
for var in list; do ... done——遍歷清單中的每個值 - 數值式:
for ((i=0; i<10; i++)); do ... done——類似 C 語言的語法
除錯技巧#
Shell Script 的除錯不像程式語言有完整的 debugger,但有幾個實用的方法:
bash -n script.sh:語法檢查,不實際執行bash -v script.sh:執行前顯示每一行原始碼bash -x script.sh:執行時顯示每個指令展開後的內容(最常用)
bash -x是 Shell Script 除錯的救命工具。它會在每個指令前顯示+號,並展開所有變數的值,讓你清楚看到實際執行的是什麼。在 CI/CD 環境中,開啟set -x能幫助快速定位腳本執行失敗的位置。
撰寫良好 Script 的原則#
- 總是加上 Shebang:不要假設執行環境的預設 Shell
- 使用
set -euo pipefail:在 script 開頭加上這行,讓錯誤即時中止、未定義變數報錯、管線中的錯誤被捕捉 - 變數加引號:
"$variable"而不是$variable,避免空值或空格造成的問題 - 使用有意義的回傳碼:成功回傳 0,不同的失敗情況回傳不同的非零值
- 寫註解:解釋「為什麼」而不是「做什麼」