きゃまなかのブログ

新卒6年目の WEB エンジニアです。 Ruby on Rails の TIPS を中心にブログ書いてます。 去年まで運用・保守のエンジニアだったので、サーバサイドの記事もたまに書きます。 よろしくお願いします。

【WordPress】定期的にバックアップを取るクーロンをシェルスクリプトで実装

概要

WordPress ではアップデートやプラグイン追加の際に、何か問題が発生する可能性があるので、定期的にバックアップを取っておくのが良いとされています。

もちろん WordPress には定期的にバックアップを取ってくれるプラグインも用意されています。

www.kagoya.jp

しかし、ふと『定期的にバックアップを取るクーロンぐらい自分で実装できなのか?』と思いました。

プラグインを利用した方が便利で早いのですが、勉強がてらスクリプトを作ってみました。

ソースコード

DB のバックアップ

mysqldump を使って定期的に DB のデータをバックアップします。

スクリプトにパスワードを直書きするのは危険なので、キーペアを使って暗号化する事にしました。

事前にパスワードなしで扱えるキーペアを用意しておきます。

$ openssl genrsa 4096 > private-key.pem
Generating RSA private key, 4096 bit long modulus
.................................++
..................................................................++
e is 65537 (0x10001)
 
# 秘密鍵は Permission 600 にする
$ chmod 600 private-key.pem

$ openssl rsa -in private-key.pem -pubout -out public-key.pem
writing RSA key

$ openssl rsa -in private-key.pem -pubout -out public-key.pem
writing RSA key

$ echo "パスワード入力" | openssl rsautl -encrypt -pubin -inkey public-key.pem -out password.enc

パスワードを暗号化したファイルが用意できました。

これを使って mysqldump するスクリプトを作成します。

#!/bin/sh

# アカウント
USER='bn_wordpress'
PASS=`openssl rsautl -decrypt -inkey private-key.pem -in password.enc`

# DB 情報
DB_NAME='bitnami_wordpress'
DB_HOST='localhost'
DB_PORT=3306

# ファイル周り
FILE_TIMESTAMP=`date "+%Y%m%d-%H%M"`
LOG_TIMESTAMP=`date "+%Y/%m/%d %H:%M"`
DUMP_FILE=/tmp/dump_$FILE_TIMESTAMP.sql
TRACE_LOG=/tmp/mysqldump_wordpress.log

# コマンド
/opt/bitnami/mysql/bin/mysqldump -u $USER -h $DB_HOST --port $DB_PORT -p$PASS $DB_NAME > $DUMP_FILE

# 実行結果
if [ $? -eq 0 ]; then
  echo "[$LOG_TIMESTAMP] [OK] $DUMP_FILE" >> $TRACE_LOG
else
  echo "[$LOG_TIMESTAMP] [NG] $DUMP_FILE" >> $TRACE_LOG
  exit 1 # 異常終了
fi

# サーバのディスク容量を圧迫するのでバックアップは 5 つまで
count=`ls -td /tmp/dump_*.sql | wc -l`
if [ $count -gt 5 ]; then
  oldest_bk_sql=`ls -td /tmp/dump_*.sql | tail -n 1`
  rm -rf $oldest_bk_sql
fi

スクリプトを実行します。

対話式じゃないので Warnning が出てしまいます。無視して下さい。

$ sh mysqldump.sh
mysqldump: [Warning] Using a password on the command line interface can be insecure.

# バックアップが最大 5 つ作られます
$ ls -la /tmp/dump_*.sql
-rw-r--r-- 1 bitnami bitnami     0 Oct 22 13:08 /tmp/dump_20181022-1308.sql
-rw-r--r-- 1 bitnami bitnami 80822 Oct 22 13:10 /tmp/dump_20181022-1310.sql
-rw-r--r-- 1 bitnami bitnami 80822 Oct 22 13:21 /tmp/dump_20181022-1321.sql
-rw-r--r-- 1 bitnami bitnami 80822 Oct 22 13:22 /tmp/dump_20181022-1322.sql
-rw-r--r-- 1 bitnami bitnami 80822 Oct 22 13:24 /tmp/dump_20181022-1324.sql

# 実行結果もログに吐いています
$ cat /tmp/mysqldump_wordpress.log
[2018/10/22 13:10] [OK] /tmp/dump_20181022-1310.sql
[2018/10/22 13:21] [OK] /tmp/dump_20181022-1321.sql
[2018/10/22 13:22] [OK] /tmp/dump_20181022-1322.sql
[2018/10/22 13:24] [OK] /tmp/dump_20181022-1324.sql

クーロン化の作業は最後にします。

ソースコードバックアップ

 

無視してください。

#!/bin/sh

FILE_TIMESTAMP=`date "+%Y%m%d-%H%M"`
LOG_TIMESTAMP=`date "+%Y/%m/%d %H:%M"`

WP_BK=/tmp/wordpress.bk-
WP_BK_AST=$WP_BK*
WP_BK_AST_TAR=$WP_BK_AST.tar.gz

DST=$WP_BK$FILE_TIMESTAMP
SRC=/home/bitnami/apps/wordpress/htdocs

DIFF_LOG=/tmp/diff_backup_wordpress.log

# バックアップ
cp -R $SRC $DST

# 実行結果
if [ $? -eq 0 ]; then
  echo "[LOG_TIMESTAMP] [OK] BackUp $DST" >> $DIFF_LOG
else
  echo "[LOG_TIMESTAMP] [NG] BackUp $DST" >> $DIFF_LOG
fi

# 最初の 1 回目はこれで終了
is_first=`ls -td $WP_BK_AST | grep -v '.tar.gz' | wc -l`
if [ $is_first -eq 1 ]; then
  exit 0
fi

# 1 つ前のバックアップディレクトリは圧縮する
bk_dir=`ls -td $WP_BK_AST | grep -v '.tar.gz' | tail -n 1`
bk_dir_tar=$bk_dir.tar.gz
tar -zcvf $bk_dir_tar $bk_dir > /dev/null
if [ -f $bk_dir_tar ]; then
  # 1 つ前のバックアップと今回のバックアップの差分を抽出
  echo "`diff -r $bk_dir $DST`" >> $DIFF_LOG
  rm -rf $bk_dir
fi

# サーバのディスク容量を圧迫するのでバックアップの tar は 5 つまで
count=`ls -td $WP_BK_AST_TAR | wc -l`
if [ $count -gt 5 ]; then
  oldest_bk_dir=`ls -td $WP_BK_AST_TAR | tail -n 1`
  rm -rf $oldest_bk_dir
fi

スクリプトを実行します。

tar の対象ディレクトリを絶対パスで指定しているため Warnning が起こります。無視して下さい。

$ sh backup_wordpress.sh
tar: Removing leading '/' from member names

$ ls -ld /tmp/wordpress.* -rw-r--r-- 1 bitnami bitnami 22961086 Oct 22 13:31 /tmp/wordpress.bk-20181022-1330.tar.gz -rw-r--r-- 1 bitnami bitnami 22954219 Oct 22 13:32 /tmp/wordpress.bk-20181022-1331.tar.gz drwxr-xr-x 5 bitnami bitnami 4096 Oct 22 13:32 /tmp/wordpress.bk-20181022-1332 # 差分があるときは以下のようにログに抽出# 差分があるときは以下のようにログに抽出 $ less /tmp/diff_backup_wordpress.log [2018/10/22 14:04] [OK] BackUp /tmp/wordpress.bk-20181022-1404
[2018/10/22 14:05] [OK] BackUp /tmp/wordpress.bk-20181022-1405
Only in /tmp/wordpress.bk-20181022-1404: htdocs
[2018/10/22 14:06] [OK] BackUp /tmp/wordpress.bk-20181022-1406
diff -r /tmp/wordpress.bk-20181022-1405/wp-admin/about.php /tmp/wordpress.bk-20181022-1406/wp-admin/about.php
22c22
< <h1><?php printf( __( 'Hello Welcome to WordPress&nbsp;%s' ), $display_version ); ?></h1>
---
> <h1><?php printf( __( 'Welcome to WordPress&nbsp;%s' ), $display_version ); ?></h1>
[2018/10/22 14:09] [OK] BackUp /tmp/wordpress.bk-20181022-1409
Only in /tmp/wordpress.bk-20181022-1406/wp-content/uploads/2018/10: coffee-100x100.jpg
Only in /tmp/wordpress.bk-20181022-1406/wp-content/uploads/2018/10: coffee-1024x614.jpg
Only in /tmp/wordpress.bk-20181022-1406/wp-content/uploads/2018/10: coffee-150x150.jpg

スクリプトのクーロン化

mysqldump.sh と backup_wordpress.sh と同じディレクトリに用意して下さい。

#!/bin/sh

CURRENT=`pwd`

echo "0,30 * * * * /bin/sh $CURRENT/mysqldump.sh" > ./crontab.txt
echo "5,35 * * * * /bin/sh $CURRENT/backup_wordpress.sh" >> ./crontab.txt

# 起動
/usr/bin/crontab ./crontab.txt
# 確認
/usr/bin/crontab -l

スクリプトを実行すると crontab が生成されました。

$ sh create_crontab.sh
0,30 * * * * /bin/sh /home/bitnami/mysqldump.sh
5,35 * * * * /bin/sh /home/bitnami/backup_wordpress.sh

これで予定通り定期的に実行されていることがログで確認できれば OK です!

今回は AWS の Ubuntu 環境を使ってスクリプトを組んだのでパスとかが異なる可能性があるので注意して下さい。

注意点

今回のスクリプトは /tmp 以下にバックアップを取っています。

/tmp 以下は reboot した時に全て消えてしまうので注意してください。

reboot したとしても残しておきたいのであれば他の場所を指定して下さい。

最後に

データベースをロールバックする場合は以下のコマンドです。

$ mysql -u bn_wordpress -p bitnami_wordpress < /tmp/dump_20181022-1445.sql