概要

以前も作成していた、MySQLのデータベースのバックアップを自動的に取得するスクリプトを少々リファインさせました。

変数指定により、複数のDBを任意にバックアップできます。

スクリプトの動き

  • サーバ内にあるDBのバックアップを取得し、暗号化して指定ディレクトリに保存します。
  • 複合化のパスワードはスクリプトが自動生成し、暗号化と同時に別ディレクトリに保存します。
  • cronの自動実行を前提としているため、古い暗号化ファイルと複合化のパスワードは一定期間後に削除を行います。

動作を確認したサーバ

  • Ubuntu 24.04
  • MySQL 8.0.39

前準備

アカウントファイル

任意のディレクトリに、db_account.txtといった、DBにユーザー名とパスワードを記したファイルを作成しておきます。

[client]
user = db_user
password = "password"
  • パーミッションは400にします。(chmod 400 db_account.txt)
  • 取り扱いは慎重に行ってください。

バックアップDBの格納先

  1. 冗長性があり
  2. 機密性が保たれる

場所を指定してください。筆者はクラウドストレージ(wasabi)をマウントしています。

パスワードの格納先

/home/hoge/dbrestore_password のように、複合化のパスワードを格納するディレクトリを作っておきます。
こちらも運用に合わせ、適切に保管ができる場所を指定します。

それぞれ、スクリプト実行アカウントがアクセス/実行できるものにします。

スクリプト

スクリプト内容

  • スクリプトファイル名(例)
    • mysql_db_backup.sh

変数などは間違いの無いように指定ください。

#!/bin/bash

## 変数ここから ##
# $HOMEの変数を指定します。
HOME_DIR="/home/hoge"
# SQLをバックアップするディレクトリ(保管先)を指定します。運用に合わせて指定ください。
backup_dir="/path/to/backup/directory"
# 保持するバックアップの世代を日数で指定します。
keep_days=7
# ファイルに付与する日付/作業ディレクトリ名/バックアップファイル名を指定します。
current_date=$(date +%Y%m%d)
backup_name="backup_mysql_${current_date}"
zip_file="backup_mysql.${current_date}.zip"
# アカウントファイルを指定します。運用に合わせて指定ください。
credentials_file="${HOME_DIR}/script/config/db_account/db_account.txt"
# パスワードを記録するファイル名を指定します。運用に併せてして指定ください。
password_dir="${HOME_DIR}/dbrestore_password"
password_file="${password_dir}/db-restore.${current_date}.txt"
# redmineのデータベース名を指定します。
database_name=database
# バックアップ時に指定するオプションを指定します。
options="--defaults-extra-file=$credentials_file --no-tablespaces --single-transaction"
# バックアップファイルのパターンを指定します。
backup_file_pattern="backup_mysql.*.zip"
# パスワードファイルのパターンを指定します。
password_file_pattern="*restore*.txt"
## 変数ここまで ##

## 処理ここから ##

# 1.アカウントファイルのパーミッションが400かどうかチェックします。
# 400以外は処理そのものを終了します。
permissions=$(stat -c "%a" "$credentials_file")
if [ "$permissions" != "400" ]; then
echo "アカウントファイルのパーミッションは400である必要があります。"
exit 1
fi

# 2.一時的なバックアップディレクトリを作成します。
mkdir "${backup_dir}/${backup_name}"

# 3. mysqldumpを実行してデータベースのバックアップを取ります。
mysqldump $options -h localhost $database_name > "${backup_dir}/${backup_name}/${backup_name}.sql"

# 4. パスワードによる暗号化を実施します。
password=$(openssl rand -base64 12)
cd "${backup_dir}/${backup_name}"
zip -r "${backup_dir}/${zip_file}" -P "$password" .
cd -

# 5. 一時的なバックアップディレクトリを削除します。
rm -rf "${backup_dir}/${backup_name}"

# 6. 解凍パスワードを指定ディレクトリに保存します。
echo $password > $password_file

# 7.パスワードの読み取り権限を600に変更します。
chmod 600 $password_file

# 8. 保持期間より古いバックアップファイルを削除します。
find "$backup_dir" -name "$backup_file_pattern" ! -type f -newermt "${keep_days} days ago" -delete
find "$password_dir" -name "$password_file_pattern" ! -type f -newermt "${keep_days} days ago" -delete

## 処理ここまで ##

作成後、

chmod +x mysql_db_backup.sh

で実行権を付与します。

スクリプトの動かし方

スクリプトの動き

./mysql_db_backup.sh

として実行すると、

  1. 変数で指定したアカウントファイルを読み込み、mysqldumpでバックアップを取ります。
  2. バックアップ作成後、パスワード付きzipファイルに圧縮します。
  3. 圧縮されたバックアップと複合化のためのテキストファイルを変数で指定したディレクトリに格納します。
  4. 変数で指定した期日が過ぎたバックアップファイルと複合化のためのテキストファイルは自動的に削除されます。

バックアップDBの解凍

unzip backup_mysql.yyyymmdd.zip

とすると、パスワードを尋ねられます。

db-restore.yyyymmdd.txtに表示された文字列を入力します。

または、

unzip -P $(cat /path/to/password_file.txt) /path/to/zip_file.zip -d /path/to/output_directory

でファイルを直接引数にして解凍することもできます。

cronの指定

動作を確認したら、

crontab -e -u hoge

でcron編集画面を出し、

0 2 * * * /home/hoge/script/directory/mysql_db_backup.sh

などとして指定すれば、日次のDBバックアップを取得可能です。