実践LESSON 09
この教材で学ぶこと Bash特有の挙動と、安全な自動化の実践パターンを学びます。Bash シェルスクリプト実践
対象読者: 基本的なプログラミング経験があり、Bash 特有の罠・イディオム・実践パターンを学びたい人。
1. Bash の「罠」— 他言語経験者が踏みやすい
# ❌ 変数展開の罠:スペースが入ると2引数になる
FILE="my file.txt"
rm $FILE # → rm my file.txt(2つの引数)
rm "$FILE" # ✅ クォートで囲む(常にこちら)
# ❌ 比較演算子の違い
if [ $a == $b ] # 文字列比較([[ ]] 推奨)
if [ $a -eq $b ] # 数値比較
if [[ $a == $b ]] # ✅ 推奨(Word splitting なし)
# ❌ コマンド失敗を無視する(デフォルト動作)
cp /src /dst
rm /important # cp が失敗しても rm が実行される
# ✅ エラーで即停止(スクリプト先頭に書く)
set -euo pipefail
# -e: エラーで即終了
# -u: 未定義変数をエラー
# -o pipefail: パイプ途中のエラーも検知
2. スクリプトの基本構造
#!/usr/bin/env bash
set -euo pipefail
# 定数
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly LOG_FILE="/var/log/myapp/deploy.log"
# ログ関数
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; }
error() { echo "[ERROR] $*" >&2; exit 1; }
# 引数チェック
usage() {
cat <<EOF
Usage: $0 [OPTIONS] <environment>
Options:
-r, --region AWS region (default: ap-northeast-1)
-d, --dry-run Dry run mode
Example:
$0 --region ap-northeast-1 prod
EOF
exit 1
}
# 引数パース
REGION="ap-northeast-1"
DRY_RUN=false
while [[ $# -gt 0 ]]; do
case $1 in
-r|--region) REGION="$2"; shift 2 ;;
-d|--dry-run) DRY_RUN=true; shift ;;
-h|--help) usage ;;
*) ENVIRONMENT="$1"; shift ;;
esac
done
[[ -z "${ENVIRONMENT:-}" ]] && usage
log "Deploy to $ENVIRONMENT (region: $REGION, dry-run: $DRY_RUN)"
3. よく使うパターン集
ファイル・ディレクトリ操作
# ファイル存在チェック
[[ -f "$FILE" ]] || error "ファイルが存在しない: $FILE"
[[ -d "$DIR" ]] || mkdir -p "$DIR"
# 一時ファイル(終了時に自動削除)
TMPFILE=$(mktemp)
trap 'rm -f "$TMPFILE"' EXIT
# ファイルの最終N行を監視
tail -f /var/log/nginx/error.log | grep -E "ERROR|WARN"
テキスト処理
# CSV の2列目を合計(awkはインフラ必須)
awk -F',' '{sum += $2} END {print sum}' data.csv
# ログから特定時間帯を抽出
awk '/2026-03-06 15:0[0-5]/' /var/log/app.log
# sed で設定ファイルの値を書き換え
sed -i 's/^MAX_CONNECTIONS=.*/MAX_CONNECTIONS=200/' /etc/app/config
# JSON を整形(jq はインフラで必須)
aws ec2 describe-instances | jq '.Reservations[].Instances[] | {id: .InstanceId, type: .InstanceType}'
# 特定列だけ表示
ps aux | awk '{print $1, $2, $11}' | column -t
プロセス・サービス管理
# PID ファイルを使った二重起動防止
PIDFILE="/var/run/myapp.pid"
if [[ -f "$PIDFILE" ]] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
error "既に起動中 (PID: $(cat "$PIDFILE"))"
fi
echo $$ > "$PIDFILE"
trap 'rm -f "$PIDFILE"' EXIT
# バックグラウンドジョブの管理
job_ids=()
for host in server1 server2 server3; do
ssh "$host" "systemctl restart app" &
job_ids+=($!)
done
# 全ジョブの完了を待つ
for pid in "${job_ids[@]}"; do
wait "$pid" || error "ジョブ失敗 PID: $pid"
done
log "全サーバーへのデプロイ完了"
4. 実践スクリプト — AWS EC2 ヘルスチェック
#!/usr/bin/env bash
set -euo pipefail
# 全リージョンのEC2インスタンス状態を確認
check_ec2_health() {
local region="${1:-ap-northeast-1}"
log "Checking EC2 instances in $region..."
# AWS CLI + jq でインスタンス一覧取得
aws ec2 describe-instances \
--region "$region" \
--query 'Reservations[].Instances[].[InstanceId,InstanceType,State.Name,Tags[?Key==`Name`].Value|[0]]' \
--output text | \
while IFS=$'\t' read -r id type state name; do
printf "%-20s %-15s %-15s %s\n" "$id" "$type" "$state" "${name:-N/A}"
done
}
# ステータスに応じて色付き出力
colorize() {
while IFS= read -r line; do
if [[ "$line" == *"running"* ]]; then
echo -e "\033[32m$line\033[0m" # 緑
elif [[ "$line" == *"stopped"* ]]; then
echo -e "\033[31m$line\033[0m" # 赤
else
echo "$line"
fi
done
}
check_ec2_health "ap-northeast-1" | colorize
5. cron・定期実行
# crontab -e で編集
# 書式: 分 時 日 月 曜日 コマンド
# 毎日午前2時にバックアップ
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# 5分ごとにヘルスチェック
*/5 * * * * /opt/scripts/health_check.sh
# 平日9時にレポート生成
0 9 * * 1-5 /opt/scripts/daily_report.sh
# systemd timer(cron より推奨)も参照: 02_Infrastructure/Linux/
6. デバッグ
# 実行トレース(各コマンドを表示)
set -x
# ... デバッグしたい処理 ...
set +x
# スクリプト全体をトレース
bash -x script.sh
# 変数の内容確認
declare -p MY_ARRAY # 配列の中身をダンプ
🔗 次のステップ
- ../../02_Infrastructure/Linux/01_Linux実践.md — Bash を活かした Linux 管理
- ../../06_DevOps/CICD/01_GitHub_Actions.md — シェルスクリプトを CI/CD で活用