ダメプログラマの技術メモ

プログラミングの技術メモや駄文など

EC-CUBEのデータ(MySQL)の自動バックアップとリストアの方法

2013/08/28頃からロリポップWordPressサイトの改ざん被害が多数報告されるようになりました。

 
設定ファイルの情報が抜き出されて、データベースの内容が書き換えられてしまったのが原因のようです。

現在運営しているEC-CUBEでも同様の現象が発生する可能性があり、また不測の事態が発生しても迅速に業務を再開させることができるように、データベースをバックアップ/リストアすることにしました。

というか今までは面倒だからバックアップをとっていなかった(;><)

被害に遭われた方には申し訳ないですが、今回の問題はリスク管理を高めるよいきっかけになりました。


EC-CUBEのデータの自動バックアップとリストアを行うのに必要な作業は次のとおりです。

  1. mysqldumpを使用してバックアップを行うシェルスクリプトを作成
  2. 定期実行するようにcronにシェルスクリプトを登録
  3. 問題が発生した場合はバックアップファイルをもとにリストア

順を追って説明します。

なお、ロリポップ(チカッパプラン)のsshの使用を前提に話を進めるので、参考にされる方は環境の差異にご注意下さい。


mysqldumpを使用してバックアップを行うシェルスクリプトを作成

ディレクトリの作成

サーバにログインしてから、binディレクトリとbackupディレクトリを作成します。

% mkdir ~/web/bin
% mkdir ~/backup

binディレクトリの中にバックアップを行うシェルスクリプト、backupディレクトリの中にバックアップファイルが入ります。

本当はbinディレクトリもwebディレクトリと同階層に作成したかったのですが、ロリポップではcron実行するシェルスクリプトはwebディレクトリ以下に作成しないといけないため、仕方なくwebディレクトリの下に作成します。


.htaccessの作成

binディレクトリの中に.htaccessを作成します。

% cd ~/web/bin
% echo deny from all > .htaccess
% chmod 604 .htaccess

シェルスクリプト内にDB接続情報を記述するので、.htaccessでhttpによるアクセスを全て拒否する(deny from all)ことにします。


シェルスクリプトの作成

% vi db_backup.sh

#下の内容でdb_backup.shを作成します。

#!/bin/sh

DAYS=7
BACKUP_PATH=/home/xxxxx/xxxxx/xxxxx/backup
BACKUP_FILE=`date +%Y%m%d`.sql.gz
OLD_BACKUP_FILE=`date -d "-$DAYS days" +%Y%m%d`.sql.gz
DB_USER=db_user
DB_PASS=db_pass
DB_SERVER=db_server
DB_NAME=db_name

cd $BACKUP_PATH
mysqldump -u $DB_USER -p$DB_PASS -h $DB_SERVER $DB_NAME | gzip > $BACKUP_FILE
chmod 600 $BACKUP_FILE
rm -f $OLD_BACKUP_FILE

シェルスクリプト作成後は他人が実行できないようにパーミッションを700に変更します。

% chmod 700 db_backup.sh

ロリポップのcronはログインユーザの権限で実行するため、自身に実行権限があれば問題ありません。


シェルスクリプトの内容について

DAYS=7

バックアップファイルを残しておく日数を設定します。

DAYS=7の場合は6日前までのバックアップファイルが保存されます。


BACKUP_PATH=/home/users/xxxxx/xxxxx/backup

バックアップファイルを保存するディレクトリをフルパスで設定します。


BACKUP_FILE=`date +%Y%m%d`.sql.gz
OLD_BACKUP_FILE=`date -d "-$DAYS days" +%Y%m%d`.sql.gz

バックアップファイル名を設定します。

20130901.sql.gzのような日付が入ったファイル名になります。

BACKUP_FILEは本日付けで新たに作成されるバックアップファイル、OLD_BACKUP_FILEは削除されるバックアップファイルになります。


DB_USER=db_user
DB_PASS=db_pass
DB_SERVER=db_server
DB_NAME=db_name

MySQLのユーザ名、パスワード、ホスト名(IPアドレス)、データベース名を設定します。

EC-CUBEのdata/config/config.phpの中に次のような記述があるので、それをそのまま設定すればOKです。

define ('DB_USER', 'db_user');
define ('DB_PASSWORD', 'db_pass');
define ('DB_SERVER', 'db_server');
define ('DB_NAME', 'db_name');

 

cd $BACKUP_PATH
mysqldump -u $DB_USER -p$DB_PASS -h $DB_SERVER $DB_NAME | gzip > $BACKUP_FILE

バックアップディレクトリの中に移動して、mysqldumpでデータベースの内容をgzip形式でファイル出力します。


chmod 600 $BACKUP_FILE

バックアップファイルのパーミッションを自分しか参照・変更できないように600に変更します。


rm -f $OLD_BACKUP_FILE

古いバックアップファイルを削除します。

本日が9/15、DAYS=7の場合は20130908.sql.gzというファイルが削除されます。


定期実行するようにcronにシェルスクリプトを登録

ロリポップではcrontabがない代わりにcronの設定を行う専用の管理画面が用意されています。

ロリポップのユーザ専用ページ → WEBツール → cron設定からcronの設定を行います。

f:id:damepg:20130909121854j:plain

上記は1日1回午前4時にシェルスクリプトを起動する例です。

ユーザアクセスの少ない早朝などに起動するのがベターだと思います。


問題が発生した場合はバックアップファイルをもとにリストア

不測の事態によりデータベースに何らかの障害が発生した場合は、バックアップファイルをもとにデータベースの復旧を行います。

サーバにログインしてから、次のコマンドを実行します。

% cd ~/backup
% zcat [バックアップファイル] | mysql -u [ユーザ名] -p[パスワード] -h [ホスト名] [データベース名]

[バックアップファイル]はバックアップディレクトリ内にある巻き戻したい日付のファイルを指定します。

[ユーザ名]、[パスワード]、[ホスト名]、[データベース名]はシェルスクリプト内に記載してあるものを指定します。

ロリポップにはphpMyAdminが標準搭載されているので、そちらのインポート機能を利用しても構いません。

その場合はバックアップファイルを解凍することなく、gzip形式のまま取り込むことが可能です。