【新・実践シェルスクリプト講座 第3回】サーバーが爆発しても大丈夫?「3-2-1ルール」を守るクラウド連携術
こんにちは!「リナックス先生」です。
前回は、サーバーが落ちた時に自動復旧させる「監視スクリプト」を作りました。
コウ君、あれからサーバーは安定してる?
先生!前回のスクリプトのおかげで、深夜のダウンも勝手に直って通知だけ来るようになりました。
バックアップも、シーズン1で習った通り、サーバーの中に毎日保存してるので完璧です!
もう何も怖くないですね!
甘いわね…。
もし、そのVPSが動いているデータセンターが火事になったらどうするの?
あるいは、間違ってサーバーを「解約(削除)」してしまったら?
「サーバーの中にあるバックアップ」は、サーバーと運命を共にするのよ。外に逃がさなきゃ意味がないわ!
新シリーズ「新・実践シェルスクリプト講座」の第3回は、**「クラウドストレージへの自動転送」**です。
データベース(MariaDB/MySQL)をダンプし、業界標準のクラウドストレージである **Amazon S3** へ自動アップロードする、プロ仕様のBCP(事業継続計画)対策スクリプトを作成します。
本講座のカリキュラム(全4回)
今回は、データを「外」へ逃がす技術を学びます。
- 黒い画面でポチポチするな!「Webサーバー構築(LAMP環境)」をボタン一発で全自動化する【完了】
- Webサイトが死んだら自動で蘇生せよ!「サービス死活監視」と「自動再起動」【完了】
- 【今回】ローカル保存じゃ終わらない!「DBバックアップ」と「AWS S3/クラウドへの自動転送」
- 黒い画面をアプリ化!?「対話型メニュー」で作る自分だけの管理ツール
1. バックアップの鉄則「3-2-1ルール」
IT業界には、データを守るための有名なルールがあります。
- 3つのデータコピーを持つ(本番データ+バックアップ2つ)
- 2種類の異なる媒体に保存する(サーバーのディスク+クラウドなど)
- 1つは遠隔地(オフサイト)に保存する
今回は、サーバー内のデータベースを圧縮し、Amazon S3(物理的に離れた場所にある安全なストレージ)に送ることで、このルールを達成します。
2. 事前準備:AWS CLIのセットアップ
シェルスクリプトからS3を操作するには、aws-cli というコマンドツールを使います。
(※AWSのアカウントと、S3バケットの作成、IAMユーザーのアクセスキー取得は済んでいるものとします)
AWS CLIのインストール(AlmaLinux系)
# zip解凍用ツールを入れる dnf install -y unzip # AWS CLI v2のインストーラーをダウンロード&実行 curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip ./aws/install # バージョン確認 aws --version
初期設定
取得しておいたアクセスキーを設定します。
[root@server ~]# aws configure AWS Access Key ID [None]: AKIAXXXXXXXXXXXXXXXX AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Default region name [None]: ap-northeast-1 (東京リージョン) Default output format [None]: json
これで、aws s3 ls と打ってバケット一覧が見えれば準備完了です。
3. S3転送バックアップスクリプト「backup_db_s3.sh」
では、スクリプトを作成します。
仕様は以下の通りです。
- DBダンプ:
mysqldumpで全データをエクスポートし、gzipで圧縮する。 - S3転送: 作成したファイルを
aws s3 cpでクラウドへ送る。 - 古い削除: サーバー内の古いバックアップは7日で消す(ディスク圧迫防止)。
- 通知: 失敗したらDiscordに通知する(前回作成した関数を流用)。
vim backup_db_s3.sh を作成します。
#!/bin/bash
# ==========================================
# 設定エリア
# ==========================================
# DB接続情報
DB_USER="root"
DB_PASS="YourPassword123" # 実際は .my.cnf で管理するのが推奨
DB_NAME="my_database" # 全DBなら --all-databases オプションを使う
# バックアップ保存先(ローカル)
LOCAL_BACKUP_DIR="/var/backups/db"
# S3バケット名(最後にスラッシュは入れない)
S3_BUCKET="s3://my-server-backup-bucket"
# ローカル保存期間(日)
RETENTION_DAYS=7
# ファイル名定義 (例: db_backup_20260107_1200.sql.gz)
DATE_STR=$(date +%Y%m%d_%H%M)
BACKUP_FILE="db_backup_${DATE_STR}.sql.gz"
FULL_PATH="${LOCAL_BACKUP_DIR}/${BACKUP_FILE}"
# Discord Webhook URL
DISCORD_URL="https://discord.com/api/webhooks/xxxxxxxx/xxxxxxxxx"
# ログファイル
LOG_FILE="/var/log/backup_db.log"
# --- 安全設定 ---
set -u
set -o pipefail # パイプエラーも検知
# ==========================================
# 関数定義
# ==========================================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
send_discord() {
local message="$1"
local payload="{\"content\": \"📦 **[Backup Job]**\n${message}\"}"
curl -s -H "Content-Type: application/json" -X POST -d "$payload" "$DISCORD_URL"
}
# ==========================================
# メイン処理
# ==========================================
log "--- バックアップ処理開始 ---"
# 1. ディレクトリ作成
if [ ! -d "$LOCAL_BACKUP_DIR" ]; then
mkdir -p "$LOCAL_BACKUP_DIR"
fi
# 2. DBダンプ & 圧縮
log "データベースをダンプ中..."
# mysqldump実行
# --single-transaction: Web稼働中でもロックせずにバックアップ
if mysqldump -u"$DB_USER" -p"$DB_PASS" --single-transaction "$DB_NAME" | gzip > "$FULL_PATH"; then
log "ダンプ成功: $FULL_PATH"
else
log "【失敗】mysqldumpに失敗しました。"
send_discord "⛔ DBバックアップ(dump)に失敗しました!ログを確認してください。"
exit 1
fi
# 3. AWS S3へ転送
log "S3へアップロード中..."
# aws s3 cp [元] [先]
if aws s3 cp "$FULL_PATH" "${S3_BUCKET}/db/${BACKUP_FILE}"; then
log "S3転送成功: ${S3_BUCKET}/db/${BACKUP_FILE}"
send_discord "✅ DBバックアップをS3へ転送しました。\nFile: $BACKUP_FILE"
else
log "【失敗】S3への転送に失敗しました。"
send_discord "⚠️ DBダンプは成功しましたが、S3転送に失敗しました。"
# 転送失敗してもローカルにはあるので、exit 1 せずに処理を続ける(掃除へ)
fi
# 4. 古いローカルファイルの削除
log "古いバックアップを削除中(${RETENTION_DAYS}日経過)..."
find "$LOCAL_BACKUP_DIR" -name "db_backup_*.sql.gz" -mtime +$RETENTION_DAYS -delete
log "--- バックアップ処理完了 ---"
💡 プロのテクニック:S3側の掃除はどうする?
このスクリプトは「ローカルの掃除」しかしません。
S3上の古いファイルを消すために aws s3 rm ... を書くのはスマートではありません。
AWS S3には「ライフサイクルルール」という機能があり、「作成から30日経過したら自動削除する」といった設定がWebコンソールから簡単にできます。
「消す処理」はクラウド側の機能に任せるのが、バグを生まないコツです。
4. 定期実行の設定
Cronに登録します。サーバー負荷を考慮して、アクセスの少ない深夜(例えばAM 4:00)に実行します。
# 実行権限付与 chmod +x backup_db_s3.sh # crontab -e # 毎日AM 4:00に実行 0 4 * * * /root/backup_db_s3.sh >> /var/log/cron_backup.log 2>&1
5. 「リストア(復旧)」の手順も確認!
バックアップは「戻せて」初めて意味があります。
VPSが全損したと仮定して、新しいサーバーでデータを戻す手順は以下のようになります。
# 1. AWS CLIを入れて設定する (aws configure) # 2. S3からバックアップファイルを取得 aws s3 cp s3://my-server-backup-bucket/db/db_backup_20260107_1200.sql.gz . # 3. 解凍してDBに流し込む gunzip < db_backup_20260107_1200.sql.gz | mysql -u root -p my_database
この手順書をNotionや社内Wikiに残しておくところまでが、エンジニアの仕事です。
まとめ:枕を高くして寝るために
今回は「クラウドへのバックアップ転送」を自動化しました。
| 工程 | 使用コマンド | ポイント |
|---|---|---|
| ダンプ | mysqldump |
--single-transactionで停止させずに取得 |
| 圧縮 | gzip |
転送量と保管コストの削減 |
| 転送 | aws s3 cp |
CLIツールで安全にクラウドへコピー |
これで、サーバーが物理的に爆発しても、あなたのデータはAmazonの堅牢なデータセンターに残ります。
「データさえあれば、サーバーはいつでも作り直せる」。この安心感こそが、自動化の最大のメリットです。
次回予告:黒い画面をアプリに変える魔法
ここまでで、構築、監視、バックアップと、裏方の仕事はほぼ自動化できました。
しかし、日々のちょっとした作業(ログを見る、サービスの再起動、ステータス確認)のために、毎回長いコマンドを打つのは面倒ですよね?
次回は最終回。read コマンドや case 文を駆使して、「番号を選ぶだけで管理作業ができる対話型メニューツール」を作成します。
あなたの黒い画面(ターミナル)が、便利なアプリのような見た目に進化しますよ!
今回はAWS S3を使ったけど、Google Cloud StorageやDropboxなどを使いたい場合は rclone というツールがおすすめよ。
コマンドの書き方は違うけど、「作って、送る」という流れは一緒だから応用してみてね!
▼AWS CLIの練習もできる!root権限が使えるVPS


コメント