みんな大好きWordPress。だからこそ、データが飛んでしまうのはなんとしても避けたいもの。そのためには、常日頃からデータのバックアップを取っておくのが重要なのですが、いちいち手動でバックアップするのは手間なので、なるべく自動化しておきたいものです。バックアップしたいのは次の二つ:アップロードしたファイルとMySQLのダンプ。そこで、UNIX環境の勉強がてら、今このブログが設置されているXREAのサーバーから、ローカルに立てたサーバへ自動的にバックアップする体制を整えてみることにしました。今回のエントリではその方法をまとめてみました。

処理の流れ

今回XREAのサーバーに設置したWordPressのデータをバックアップするにあたっては、まず、XREAのサーバー側で、MySQLのデータをダンプし、圧縮をかけてファイルとして保存する、という処理を行います。その上で、ローカル側に設置したサーバーで、ryncという差分コピー可能なコマンドをつかい、SSHを通じてサーバーからMySQLのダンプしたデータや、アップロードした画像、WordPressの本体やプラグイン、テーマをひっくるめて同期します(Pull)。そして同期したディレクトリを元に、pdumpfsを使い世代別バックアップを作成します。この処理をcronで毎日実行してやるという流れです。

このように今回はcronやrsyncを使うために、ローカル側に、毎日その時間に起きているUNIXなマシンが必要になります。そのため今回のエントリは、ファイルサーバーにするなどで自宅サーバーを運用している人以外にはハードルが高いかも知れません。ただ、起きっぱなしのサーバーが家に一台あれば、前述のようにファイルサーバーに出来るなど何かと便利ですので、これを機に、自宅サーバー構築に手を出してみるのもおススメです:D 遊んでいるマシンがあるなら、それにLinuxを入れてしまうとか、遊んでいなくても常時起こしておけるWindowsマシンがあれば、VirtualBoxを入れてその中でLinuxを動かすとか、色々方法はあります。

バックアップ手順

まずは下ごしらえ。ローカルのサーバーからリモートのサーバー(XREA)に対して操作を行うわけですが、そのためにはSSHで接続できるようにしなければなりません。XREAへのSSHでの接続については、こちらのhiromasaさんの記事を参照。但し、今回は、バックアップの自動化が目的なので、そのプロセスで手動でのパスワードの入力を求められるのは困るので、パスフレーズを空にした鍵による公開鍵認証を使います。ssh-keygenを使ってローカルのサーバーで鍵ペアを作り、公開鍵をリモートのサーバー(XREA)に配置しましょう。鍵ペアの作り方についてはssh にてパスワードを使用しないでログインする方法を参照。

次にMySQLのダンプと圧縮。と言っても、難しいことは何もありません。これについてもhiromasaさんが既にサーバー側のcronで定期的にMySQLをダンプする方法についての記事を書かれています。これを使わせてもらいましょう。今回は、pdumpfsで世代別バックアップを取っているので、日付別に保存しないように改変したものを以下に示します。

#!/bin/sh
 
# 設定(ここを自分に合わせる)
DATABASE=
DBUSERNAME=
PASSWORD=
XREAUSERNAME=
BACKUPDIR=
KEEPDAY=14
 
# 初期化(XREA/CORESERVER用)
PREFIX=mysql
SERVER=localhost
NOWDATE=`date +%Y%m%d`
DESTDIR=/virtual/$XREAUSERNAME/$BACKUPDIR
# DUMPFILE=$PREFIX.$NOWDATE.dump
DUMPFILE=$PREFIX.dump
# TARFILE=$PREFIX.$NOWDATE.tar.gz
TARFILE=$PREFIX.tar.gz
OLDDATE=`date "-d$KEEPDAY days ago" +%Y%m%d`
 
# MySQLダンプ/圧縮
cd $DESTDIR
/usr/local/mysql/bin/mysqldump $DATABASE --host=$SERVER -u $DBUSERNAME --password=$PASSWORD > $DUMPFILE
tar zcvf $TARFILE $DUMPFILE
 
# 処理判定
if [ $? != 0 -o ! -e $TARFILE ]; then
    echo "backup faild -- ($DUMPFILE)"
    exit 1
fi
 
# 圧縮前ファイル削除
rm -f $DUMPFILE
 
# n日ローテートを削除
#rmfile=$DESTDIR/$PREFIX.$OLDDATE.tar.gz
#if [ -e $rmfile ]; then
#    rm -f $rmfile
#fi

cronの設定をしない以外は、記事の通りにXREAのサーバーに配置し、設定を書き換えてやれば大丈夫です。では、試しにSSHを通じてコマンドを発行し動かしてみましょう。ローカルのサーバーで以下のコマンドを実行してみましょう。

ssh -i <秘密鍵へのパス> <XREAのユーザー名>@<サーバ名> <hiromasaさん製スクリプトへのパス>

#ウチの環境だと以下のようになります。
ssh -i ./nopass sharplab@s333.xrea.com /virtual/sharplab/backup-mysql/mysqlbackup.sh

動きましたか?動かない?SSHの接続が拒否された?それはもしかすると、XREAのサーバーにホスト情報を登録し忘れているせいかもしれません。hiromasaさんの先ほどの記事を参考に登録を行ってみましょう。

さて、とりあえず手動で登録すればよいことは分かりましたが、登録の有効期限は30日間だけに限られています。また、出先でSSHで繋ぐために別のIPアドレスを登録した場合、上書きされてしまい、再度登録しないと繋がらなくなってしまいます。そのため、ホスト情報の登録も自動化する必要があります。そこでこんなスクリプトをPythonで書いてみました。

#!/usr/bin/env python
# vim:fileencoding=utf_8
import sys
import urllib
import re

#ここを書き換えてください
server = ''
username = ''
password = ''
ipaddressResponder = ''#'http://scripts.sharplab.net/ipaddress.php'//←ウチの場合

adminURL = 'http://%s/jp/admin.cgi' % server

try:
	ipRes = urllib.urlopen(ipaddressResponder)
	ipaddress = ipRes.read()
except:
	print u'Failed'
	sys.exit()

pattern = re.compile('\d+\.\d+\.\d+\.\d+')
if pattern.match(ipaddress) == None:
	print u'Failed'
	sys.exit();

values = {'id':username, 'pass':password,'remote_host':ipaddress,'ssh2':'SSH登録'}
data = urllib.urlencode(values)
print u'Registing ipaddress(%s)...'  % ipaddress 
response = urllib.urlopen(adminURL,data)
try:
	response.read().decode('shift_jis').index(u'データベースに追加しました。反映には5〜10分程度掛かります。')
	print u'Complete!'
except ValueError:
	print u'Failed.'

まず、前もって接続してきたホストのIPを返すPHPのページをサーバーに設置し(ipaddressResponder)、そこにアクセスすることでホストのIPアドレスを調べています。PHPのページのソースはこう。

<?php
echo getenv("REMOTE_ADDR");
?>

その上で、調べたホストのIPとユーザー名、パスワードをホストの登録ページにPOSTするだけの簡単なお仕事です。Cookieとか憶えないといけないかなと思ってPython Mechanize使おうとしたのですが、必要なかったです(笑)

さて、ここまでで、SSHを通してサーバー側でMySQLをダンプする処理と、SSHのためにホストを自動登録するスクリプトの準備が出来ました。では次はいよいよ本題、rsyncによるファイルのバックアップです。rsyncによるリモートバックアップは、リモートとSSHで繋げ、リモートにもrsyncが入っていれば使えると記憶していますが、XREAはどちらも満たしています。他のレンタルサーバーでも、SSHで繋げるところなら使えるところはあるかと思います。

ではrsyncのコマンドを。

<rsyncへのパス> -avz --delete -e 'ssh -i <秘密鍵へのパス>' <XREAのユーザー名>@<サーバー名>.xrea.com:<バックアップしたいディレクトリへのパス> <同期先へのパス>

#ウチの環境だと以下のようになります
./rsync/rsync -avz --delete -e 'ssh -i ./nopass' sharplab@s333.xrea.com:/virtual/sharplab/ ./sharplab/workspace

これでXREAのサーバーとローカルのサーバーの中身を同期させられます。rsyncは更新のあった差分のみをやり取りするので二度目以降は効率が上がるのが嬉しいですね!

そしてpdumpfs。同期したフォルダをソースに、世代別バックアップを作ってやります。pdumpfsはハードリンクを活用しているので、毎日世代別バックアップを取っても、更新がかかったファイル分位しか必要とする領域が増えないので使うのに気が楽ですね。

pdumpfs <ソースディレクトリ> <バックアップ先ディレクトリ>

//ウチの環境だと以下のようになります
pdumpfs ./sharplab/workspace/ ./sharplab/backup/

ではこれらをまとめた上でcronに登録してみましょう。

まずバックアップ処理手順をまとめたスクリプトを作成します。

#サーバーに配置したMySQLのダンプ&圧縮スクリプトを起動
ssh -i <秘密鍵へのパス> <XREAのユーザー名>@<XREAのサーバー名>.xrea.com <hiromasaさん作のスクリプトへのパス>
#サーバー全体をworkspaceディレクトリと同期
<rsyncへのパス>/rsync -avz --delete -e 'ssh -i <秘密鍵へのパス>' <XREAのユーザー名>@<XREAのサーバー名>.xrea.com:<バックアップ対象としたいディレクトリへのパス> <一時保存先のディレクトリへのパス>
#pdumpfsで世代別バックアップ
pdumpfs <一時保存先のディレクトリ> <バックアップ先>

そしてこれを毎日呼び出すようにcronを設定します。

HOME=<registHost.pyやbackup.shを配置したディレクトリ>
#毎日午前四時 SSHを使うにあたり、ホスト情報をXREAに登録
0 4 * * * <registHost.pyやbackup.shを配置したディレクトリ>/registHost.py

#毎日午前四時十分 XREAのバックアップの本処理
10 4 * * * <registHost.pyやbackup.shを配置したディレクトリ>/backup.sh

さて、最後に忘れちゃいけない作業があります。

それはバックアップのリストア作業のテスト。バックアップをとったは良いけど、実はうまく取れていなくて、いざ必要になった時に使い物になりませんでしたでは悲しすぎます。忘れずにリストア出来るか確認しておきましょう。お疲れ様でした!