SaaS開発日記

VPS(Linux)でDBバックアップ+Gmail送信機能の実装

これまでDBのバックアップはずっと手動で取っていました。必要なときにSSHで接続して mysqldump を叩く、という運用です。

ただ、これがじわじわと面倒になってきました。「あとでやろう」が積み重なると、いざというときにバックアップが古すぎて使えない……という事態も起こりかねません。

そこで、cronを使った自動バックアップの仕組みを作ることにしました。ついでに、バックアップが成功したかどうかをGmailで通知する機能も一緒に実装しています。

今回やったことの全体像

  • バックアップ専用のMySQLユーザを作成し、最小権限で運用
  • パスワードは .my.cnf で安全に管理
  • シェルスクリプトでダンプ → gzip圧縮 → 14日間保持
  • cronで毎日AM3:00に自動実行
  • 実行結果(成功 / 失敗)をGmail経由でメール通知

とくにつまずくところはありませんでした。Linux上でシェルスクリプトを書いた経験があれば、そこまで苦労しないと思います。

1. バックアップ専用ユーザの作成

まず、バックアップ用途に特化したMySQLユーザを作成します。rootでバックアップを取ることもできますが、万が一スクリプトに問題があったときのリスクを考えると、必要最小限の権限だけを持ったユーザを使うのが安全です。

MySQL
# まずMySQLにログイン
mysql -u root -p

-- バックアップ専用ユーザを作成
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'your_password';

-- バックアップに必要な最小限の権限を付与
GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, PROCESS, EVENT
  ON *.* TO 'backup_user'@'localhost';

FLUSH PRIVILEGES;
exit;
※注意: 'your_password' の部分は、実際に使用する強力なパスワードに置き換えてください。

2. パスワードを安全に管理する

スクリプト内にパスワードを直書きするのは避けたいので、~/.my.cnf にMySQL接続情報を記述しておきます。パーミッションを 600 にすることで、自分以外は読めないようにします。

~/.my.cnf
[mysqldump]
user=backup_user
password=your_password
パーミッション設定
chmod 600 ~/.my.cnf

これで mysqldump 実行時に --defaults-file オプションでこのファイルを指定すれば、コマンドラインにパスワードを書く必要がなくなります。

3. バックアップスクリプトの作成

バックアップ本体のシェルスクリプトを作成します。ダンプした結果をgzipで圧縮し、日付つきのファイル名で保存、古いファイルは自動削除する構成です。

ディレクトリ準備
mkdir -p /home/centos/scripts
/home/centos/scripts/mysql_backup.sh
#!/bin/bash
# /home/centos/scripts/mysql_backup.sh

# 設定
DB_NAME="your_dbname"
BACKUP_DIR="/var/backups/mysql"
DATE=$(date +"%Y%m%d_%H%M%S")
RETENTION_DAYS=14  # 14日分保持

# ディレクトリがなければ作成
mkdir -p "$BACKUP_DIR"

# バックアップ実行
mysqldump --defaults-file=/home/centos/.my.cnf \
  --single-transaction \
  --routines \
  --triggers \
  --databases "$DB_NAME" \
  | gzip > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"

# 結果チェック
if [ $? -eq 0 ]; then
  echo "[$(date)] Backup succeeded: ${DB_NAME}_${DATE}.sql.gz" >> "$BACKUP_DIR/backup.log"
else
  echo "[$(date)] Backup FAILED" >> "$BACKUP_DIR/backup.log"
fi

# 古いバックアップを削除
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete

--single-transaction を付けることで、InnoDB環境であればテーブルロックなしで一貫性のあるバックアップが取れます。--routines--triggers でストアドプロシージャやトリガーも含めてダンプしています。

4. 手動で動作確認

cronに登録する前に、まずスクリプトが正しく動くことを確認します。

動作確認コマンド
# 実行権限を付与
chmod +x /home/centos/scripts/mysql_backup.sh

# 手動実行
sudo bash /home/centos/scripts/mysql_backup.sh

# バックアップファイルが作成されたか確認
ls -lh /var/backups/mysql/

# 中身が正しいか先頭を確認
gunzip -c /var/backups/mysql/your_dbname_*.sql.gz | head -50

ファイルが生成されていて、head -50 でSQLの中身が確認できれば成功です。

5. cronで定期実行を登録

動作確認ができたら、crontabに登録して自動化します。

crontab登録
# cron編集画面を開く
sudo crontab -e

# 以下を追記(毎日 AM 3:00 にバックアップ実行)
0 3 * * * /bin/bash /home/centos/scripts/mysql_backup.sh

# 登録内容を確認
sudo crontab -l

これでバックアップの自動化は完了です。

過去データを持つ安心感

バックアップを定期的に取っておくことで、単なる障害復旧だけでなく「過去14日間のデータで検証できる」という安心感が得られます。本番データの変更前後を比較したいときなどに、この仕組みがあるだけで心理的にかなり楽になりました。

6. Gmail送信による結果通知

バックアップが成功したのか失敗したのか、毎回サーバーにログインして確認するのは本末転倒です。そこで、実行結果をGmail経由でメール通知する仕組みも合わせて作りました。

Googleアプリパスワードの発行

まず、Gmailからプログラム経由で送信するために、アプリパスワードを発行します。

2 アプリ名に「backup-notify」などを入力
3 表示された16桁のパスワードをメモしておく
※注意: アプリパスワードは発行時に一度しか表示されません。必ずその場で安全な場所に控えてください。

メール送信スクリプトの作成

/home/centos/scripts/send_mail.py
#!/usr/bin/env python3
import smtplib
import sys
from email.mime.text import MIMEText

GMAIL_USER = "xxxx@gmail.com"
GMAIL_APP_PASS = "xxxx xxxx xxxx xxxx"  # アプリパスワード
TO_ADDR = "xxxx@example.co.jp"

subject = sys.argv[1] if len(sys.argv) > 1 else "No Subject"
body = sys.argv[2] if len(sys.argv) > 2 else ""

msg = MIMEText(body)
msg["Subject"] = subject
msg["From"] = GMAIL_USER
msg["To"] = TO_ADDR

with smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls()
    server.login(GMAIL_USER, GMAIL_APP_PASS)
    server.send_message(msg)

送信テスト

テスト送信
python3 /home/centos/scripts/send_mail.py "test mail" "This is a test."

指定した送信先にメールが届けば成功です。あとはバックアップスクリプトの結果チェック部分からこのスクリプトを呼び出すようにすれば、バックアップの成功・失敗がメールで届くようになります。

このメール送信の仕組み自体はさほど難しくありません。バックアップの通知だけでなく、稼働中のシステムで何かしらの異常を検知したときの通知や、定期処理の完了報告など、さまざまな場面で使い回せそうです。

まとめ

今回のポイント

手動だったDBバックアップをcronで自動化し、Gmail通知と組み合わせることで「放っておいても安心」な仕組みが完成しました。過去14日間のデータを保持しているので、いざというときの復旧や検証にも対応できます。

Gmail送信の実装も簡単なので、バックアップに限らず、システム監視や定期処理の通知など幅広い用途に応用できるのが嬉しいポイントです。つまずく箇所もほとんどなく、やってみると「もっと早くやればよかった」と感じる改善でした。

-SaaS開発日記