Bash Strict Mode: set -euo pipefailの解説
set -euo pipefailでbash strict modeをマスター。各フラグの機能、一般的な落とし穴、予期される失敗の適切な処理方法を解説します。
Script Setup
詳細な説明
Bash Strict Mode
スクリプトの先頭近くにset -euo pipefailを追加すると、ほとんどの一般的なスクリプトバグをダメージが発生する前にキャッチする3つの安全設定が有効になります。
3つのフラグ
#!/usr/bin/env bash
set -euo pipefail
set -e(errexit): コマンドがゼロ以外のステータスを返した場合、即座に終了します。これがないと、スクリプトは失敗後も続行し、古いまたは欠落したデータで操作する可能性があります。
set -e
cd /nonexistent/path # スクリプトはここで終了
rm -rf * # 実行されない
set -u(nounset): 未設定の変数をエラーとして扱います。これがないと、$TYPOは暗黙的に空文字列に展開されます。
set -u
echo "$UNSET_VAR" # エラー: UNSET_VAR: unbound variable
set -o pipefail: パイプラインで最初に失敗したコマンドの終了ステータスを返します。これがないと、最後のコマンドの終了ステータスのみが使用されます。
set -o pipefail
false | true # パイプラインが失敗(falseがゼロ以外を返した)
echo "この行はset -eでは到達しない"
予期される失敗の処理
コマンドの失敗が許容される場合、以下のパターンを使用します:
# パターン1: || true
grep "pattern" file.txt || true # grepが何も見つからなくてもOK
# パターン2: if文
if grep -q "pattern" file.txt; then
echo "Found"
fi
# パターン3: 一時的に無効化
set +e
risky_command
result=$?
set -e
一般的な落とし穴
localでのコマンド置換: localキーワードがコマンド置換の終了ステータスをマスクします:
# 悪い例: localがエラーをマスク
local result=$(failing_command) # エラーが発生しない!
# 良い例: 宣言と代入を分離
local result
result=$(failing_command) # エラーが適切に発生
完全なテンプレート
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
# スクリプトをここに記述
IFS行はワードスプリッティングを改行とタブに制限し、追加の安全層を提供します。
ユースケース
特定の理由がない限り、すべてのbashスクリプトはstrict modeで開始すべきです。デプロイスクリプト、データ処理パイプライン、システム管理タスク、およびサイレントな失敗がデータ損失を引き起こす可能性のあるスクリプトで特に重要です。