WordPressデータのバックアップスクリプト作成

WPの構築は完了したが、バックアップツールを用意していなかった。

バックアップのプラグインは沢山存在するが、公開ディレクトリにデーターを保管したり、バックアップ機能はあってもリストアはPHPMyadminを利用することを前提としているような寂しいツールばかりだった(気がする)ので自分でスクリプトを作ることにした。

※2021年5月29日にバックアップファイルの定期削除処理を追加。

要件

bashで作成する。CLIで実行。

MariaDB10以降で利用可能。

スクリプトの実行だけでWebのデーター、DBのデーターどちらも取得可能とする。

難しい操作は不要とする。

自分が構築した他のサイト、スーパーユーザー以外でも(一応)再利用が可能なツールを作成する。

必要に応じて1日に複数回実行可能とする。

1日1回程度自動でデーターを取得可能とする。

リストアは個別にコマンドで対応するので考慮不要。

設計

  • シェルスクリプトで作成する。
  • 引数なしでコマンドを実行したら作業が完了するように作成。
  • バックアップファイル名に日付(YYYY-MM-DD-HH-MM)を付与することで1日に複数回実行可能とする。(1分以内に2回以上実施する際は、後の処理のみデータが残る)
  • 対象サイトの公開ディレクトリ配下の全データーをバックアップする。
  • 対象サイトに関するデーターベースすべてをバックアップする。
  • スクリプトは1つ作成し、バックアップディレクトリやDB名、DBパスワードなどは変数で格納する。
  • Webサーバーのデーターをコピーする権限さえあれば誰でも実行できるツールを作成する。
  • バックアップ自体はcronで実行する。
  • 過去30日分のバックアップを取得する。(2021年5月29日追記)
  • 古いバックアップは毎日削除する。(2021年5月29日追記)

実装

ソースコード

以下のスクリプトを作成。

任意の文字列を入れる箇所(公開ディレクトリ、DBユーザー、DBパスワード)は日本語に置換。

DBHOSTはlocalhostとしているが、外部のDBに接続する場合は、対象のサーバーのIPアドレスやFQDNに変更する必要あり。

#! /usr/bin/bash

# valiables
DATE=$(date +%Y%m)
FDATE=$(date +%F-%H-%M)
WDIR=${HOME}/wp_bkp
BLOG=${WDIR}/logs/${FDATE}.log
BDIR="PUBLIC_DIR"
BASENAME=$(basename ${BDIR})
DIRNAME=$(dirname "${BLOG}")
FARC="${BASENAME}_${FDATE}.tar.gz"
DBNAME="hoge"
DBUSER="DBUSER"
DBPASS="DBPASS"
DBHOST="localhost"
FDMP="${DBNAME}_dump_${FDATE}.gz"
RMDIR=$(date +%Y%m -d '2 month ago')

# advance preparation
WDIR=${WDIR}/${DATE}
mkdir -p "${WDIR}" && cd "${WDIR}" || exit

# file back up
mkdir -p "${DIRNAME}"
touch "${BLOG}"
echo -e "file backup log start. \n #################################################### \n" >> "${BLOG}"

tar cvzf "${FARC}" "${BDIR}" >> "${BLOG}"

echo -e "\n file backup log finished. \n ####################################################" >> "${BLOG}"

# database dump
echo -e "database dump log start. \n " >> "${BLOG}"

mysqldump -u "${DBUSER}" -p"${DBPASS}" -h "${DBHOST}" --databases "${DBNAME}" | gzip > "${FDMP}"

echo -e "\n database dump log log finished. \n ####################################################" >> "${BLOG}"

# remove old files
WDIR=$(dirname ${WDIR})

echo -e "\n directory remove log start. \n " >> "${BLOG}"
cd ../
find ./ -name *.gz -mtime +30 | xargs -i rm {}

# remove old directory
if [ -e "${WDIR}/${RMDIR}" ]; then
    if  [ -z "$(ls ${WDIR}/${RMDIR})" ]; then
        rmdir ${WDIR}/${RMDIR} >> "${BLOG}"
        echo "directory:" ${RMDIR} "has not file or directory. and, remove directory:"${RMDIR}"."  >> "${BLOG}"
    else  echo "directory:" ${RMDIR} " has file or directory." >> "${BLOG}"
    fi
else echo "remove directory:" ${RMDIR} "is not found."  >> "${BLOG}"
fi

echo -e "\n directory remove log end. \n" >> "${BLOG}"

# STOUT backup log file path
echo -e "backup log create  ${BLOG}"

変数代入部分

以下を参照。

# valiables
DATE=$(date +%Y%m)                   ←バックアップディレクトリに使用する日付を指定
FDATE=$(date +%F-%H-%M)              ←ファイル名に使用する日付を指定
WDIR=${HOME}/wp_bkp                  ←バックアップ作業ディレクトリ名を指定。ユーザ毎にPATHが変わる
BLOG=${WDIR}/logs/${FDATE}.log       ←バックアップログの置き場を指定   
BDIR="公開ディレクトリ"              ←Webサイトの公開ディレクトリ(/var/www/html等)を指定
BASENAME=$(basename ${BDIR})         ←バックアップディレクトリの一番深いディレクトリを取得
DIRNAME=$(dirname ${BLOG})           ←バックアップディレクトリの一番深いディレクトリ以外を取得
FARC="${BASENAME}_${FDATE}.tar.gz"   ←Webサイトのアーカイブファイル名を指定
DBNAME="データベース名"              ←データベース名を指定
DBUSER="DBユーザー"                  ←DBユーザー名を指定
DBPASS="DBパスワード"                ←DBパスワードを指定

作業前準備

# advance preparation
WDIR=${WDIR}/${DATE}
mkdir -p "${WDIR}" && cd "${WDIR}" || exit ←作業ディレクトリを作成し、移動

WEBサイトのデーターバックアップ

tar ~でバックアップ実施。他は特に説明箇所なし。

echoはログファイルを見やすくするためだけに実行。

# file back up
mkdir -p "${DIRNAME}"
touch "${BLOG}"
echo -e "file backup log start. \n #################################################### \n" >> "${BLOG}"

tar cvzf "${FARC}" "${BDIR}" >> "${BLOG}"

echo -e "\n file backup log finished. \n ####################################################" >> "${BLOG}"

データーベースのダンプ

mysqldump ~でダンプ実施。echoはバックアップの完了を伝えるために記載。

# database dump
echo -e "database dump log start. \n " >> "${BLOG}"

mysqldump -u "${DBUSER}" -p"${DBPASS}" -h "${DBHOST}" --databases "${DBNAME}" | gzip > "${FDMP}"

echo -e "\n database dump log log finished. \n ####################################################" >> "${BLOG}"

古いバックアップファイル、ディレクトリの削除(2021年5月29日追加)

バックアップ後、30日経過した古いファイルを削除し、YYYYMM形式で作成した古いディレクトリを削除。

# remove old files
find ./ -name *.gz -mtime +30 | xargs -i rm {}
# remove old files
WDIR=$(dirname ${WDIR})

echo -e "\n directory remove log start. \n " >> "${BLOG}"
cd ../
find ./ -name *.gz -mtime +30 | xargs -i rm {}

# remove old directory
if [ -e "${WDIR}/${RMDIR}" ]; then
    if  [ -z "$(ls ${WDIR}/${RMDIR})" ]; then
        rmdir ${WDIR}/${RMDIR} >> "${BLOG}"
        echo "directory:" ${RMDIR} "has not file or directory. and, remove directory:"${RMDIR}"."  >> "${BLOG}"
    else  echo "directory:" ${RMDIR} " has file or directory." >> "${BLOG}"
    fi
else echo "remove directory:" ${RMDIR} "is not found."  >> "${BLOG}"
fi

echo -e "\n directory remove log end. \n" >> "${BLOG}"

# STOUT backup log file path
echo -e "backup log create  ${BLOG}"

スクリプトの実行

 ./bkp_wp.sh
tar: Removing leading `/' from member names
backup data create  /root/wp_bkp/202105
backup log create  /root/wp_bkp/logs/2021-05-07-03-48.log

ファイルの確認

#バックアップファイルの有無確認
ls -la /root/wp_bkp/202105
total 85296
drwxr-xr-x 2 root root     4096 May  7 03:48 .
drwxr-xr-x 4 root root     4096 May  7 03:48 ..
-rw-r--r-- 1 root root 87172949 May  7 03:48 tech-memo.net_2021-05-07-03-48.tar.gz
-rw-r--r-- 1 root root   158652 May  7 03:48 hoge_dump_2021-05-07-03-48.gz

#バックアップログの確認
head /root/wp_bkp/logs/2021-05-07-03-48.log
file backup log start.

 ####################################################

/var/www/tech-memo.net/
/var/www/tech-memo.net/license.txt
.........

crontab登録

登録を確認。登録方法はviでもcrontabでも無問題。

crontab -e -u webmaster
cat /var/spool/cron/webmaster
2 4 * * * /home/webmaster/bkp_wp.sh

ログで実行されたことを確認。

tail /var/log/cron
.........
May  7 04:02:01 localhost crond[1162]: (webmaster) RELOAD (/var/spool/cron/webmaster)
May  7 04:02:02 localhost CROND[35341]: (webmaster) CMD (/home/webmaster/bkp_wp.sh)

リストア

リストア手順

データー削除(本来は不要です)

実際にデーターを消して試してみる。直前にバックアップ取得済。

# Webサイトのデーター削除
rm -rf /var/www/tech-memo.net 

# DB削除
 mysql -p
Enter password:

MariaDB [(none)]> drop database hoge;
Query OK, 19 rows affected (0.183 sec)

サイトを確認。しっかりお亡くなりになってらっしゃる。

うわあああ。やっちまったー。ぶくぶく(泡を吹いている音)。

リストア実行

Webバックアップ復元

webmasterは/var/www配下のファイルを修正する権限がないため、以下コマンドはrootで実施。

#アーカイブファイルを解凍。
cd /home/webmaster/wp_bkp/202105/
tar -xvzf tech-memo.net_2021-05-07-15-42.tar.gz

#考慮漏れでディレクトリ構造までコピーしてしまったため、tech-memo.net配下だけ公開ディレクトリに移動。
mv ./var/www/tech-memo.net /var/www/

ようやくサイトにアクセスできる状態まで戻る。

DBダンプファイル復旧

空のDBを作成後にリストア作業を実施。


# 空DB作成
mysql -p
 -uroot
Enter password:

create database hoge;
Query OK, 1 row affected (0.001 sec)

# リストア
zcat hoge_dump_2021-05-07-15-42.gz | mysql -p hoge -uroot
Enter password:  ←MariaDBのrootパスワード入力

リストア後、サイトが正常な状態に戻ったことを確認。

mysql_config_editorがMariaDBでは利用できないことが発覚

スクリプトにパスワードをべた書きするのはカッコ悪いなあと思っていたが、MySQL5.6以降のバージョンだとmysql_config_editorというツールを利用すれば別ファイルに暗号化して書き出してくれるらしい。

mysql_config_editorを使ってパスワードのベタ書きを回避 – tsunokawaのはてなダイアリー概要 MySQLのDBダンプのスクリプトなどパスワードをベタ書きしている場合があります。例えば mysqldump -u dbdump –password=dbdump testdb (オプション略)こんな感じでパスワードを書いてしまっています。そこでmysql_config_editor(MySQL5.6以上)を使…

tsunokawa.hatenablog.com

MariaDBがサポートしていないコマンドであることが発覚。

mysql_config_editor compatibilityDoes mariadb 10 (“equivalent” of mysql 5.6) support the mysql5.6 “–login-path=local” feature which is set with mysql_config_editor command? What is the mariad…

mariadb.com

細かいことを言うとmysql_config_editorを使うとプロンプト上だとパスワード無しでログインできてしまうことを確認。スクリプト上でログイン情報を非表示にできても、ログイン後にパスワードが不要になる仕組みは意図したものと違いセキュリティのリスクが下がることはないと思うのでそもそも適用しないことにした。
MariaDB側も同じ意見のためmysql_config_editorをサポートしないと判断したらしい。

あとは、今のスクリプトだと実行するごとにサーバーが管理者と判断するメアドにメールを発砲してしまうため不要であればそこの対応も必要。(今回は特に対応しないことにした)

多少の変更は必要ですなあ、時間を作って改良版を作成しようと思う。

コメント

タイトルとURLをコピーしました