管線把前一個指令的 stdout 接到下一個指令;重新導向則決定 stdin、stdout、stderr 要去哪裡。最容易踩到的是 > 會截斷舊檔,以及沒開 pipefail 時只看到最後一段的結束碼。
動手前:正式檔案輸出先用新檔名。不要把密碼或 token 直接放進環境變數示範後貼到工單;命令替換與 eval 也不能吃未驗證的外部輸入。
管線與條件執行
把輸出交給下一個指令Bash/Zsh
printf 'ERROR
INFO
' | grep 'ERROR'| 只傳 stdout。
成功才執行下一步Bash/Zsh
test -f app.conf && echo 'found'前一個指令 exit code 為 0 才執行右邊。
失敗才執行替代步驟Bash/Zsh
test -f app.conf || echo 'missing'前一個指令非 0 才執行右邊。
依序執行,不看成功失敗Bash/Zsh
date; uptime; 不提供錯誤保護。
查看上一個 exit codeBash/Zsh
printf '%s
' "$?"必須緊接在要檢查的指令後。
讓管線任何一段失敗都回失敗Bash
set -o pipefail腳本常搭配 set -euo pipefail,但要理解每個選項的行為。
對整條管線計時Bash
time grep 'ERROR' app.log | wc -lBash 保留字 time 可以量整條 pipeline。
輸入輸出重新導向
輸出到新檔或覆蓋舊檔Bash/Zsh
command > output.txt> 會截斷既有 output.txt。
追加到檔案Bash/Zsh
command >> output.txt不清除既有內容。
只把錯誤寫到檔案Bash/Zsh
command 2> error.logstdout 仍顯示在終端機。
stdout 與 stderr 寫同一檔Bash/Zsh
command > combined.log 2>&1順序重要:先把 stdout 指到檔案,再讓 stderr 跟隨。
同時顯示並保存Linux/macOS
command | tee output.txttee 預設覆蓋;追加使用 tee -a。
把 stderr 也送進 teeBash/Zsh
command 2>&1 | tee combined.log會把兩種輸出合併,時間順序仍可能受 buffering 影響。
從檔案讀 stdinBash/Zsh
sort < names.txt效果等同讓 sort 開啟該檔,但適合說明資料流。
丟棄一般輸出Linux/macOS
command > /dev/null錯誤仍會顯示。
變數與多行輸入
設定目前 shell 變數Bash/Zsh
APP_ENV=staging尚未 export,子程序看不到。
匯出環境變數Bash/Zsh
export APP_ENV=staging後續子程序可以讀到。
只替單一指令設定環境Bash/Zsh
APP_ENV=staging command不會永久留在目前 shell。
查看單一環境變數Bash/Zsh
printf '%s
' "$APP_ENV"雙引號避免空白與萬用字元拆分。
取消變數Bash/Zsh
unset APP_ENV後續程序不再繼承此變數。
把指令輸出存到變數Bash/Zsh
current_date=$(date +%F)不要對未信任輸入使用 eval。
使用 here documentBash/Zsh
cat <<'EOF'
line one
$THIS_IS_NOT_EXPANDED
EOF分隔符加單引號會阻止變數展開。
用 printf 取代不確定的 echoBash/Zsh
printf '%s\n' "$value"對反斜線與 -n 開頭內容更可預期。
怎麼確認有做對
- 檢查 exit code 與輸出檔大小。
- 腳本用 shellcheck 或至少 bash -n 做語法檢查。
- 重要 pipeline 開 pipefail 並刻意測試中間步驟失敗。
常見錯誤
- > 與 >> 用反而清空舊檔。
- 2>&1 的順序放錯。
- 變數沒有加雙引號。
- 以為 pipeline 的 exit code 會自動代表所有階段。
- 把 secret 直接印到 log。
版本與官方文件
參數會隨工具版本與作業系統實作改變。正式環境先用 --help、-h 或系統內建說明確認,再以當版官方文件為準。