2026年5月30日

2026年5月30日

WordPressのバックアップを自動化するBashスクリプトの作り方|WP-CLIとcron

このスクリプトでできること

VPSや専用サーバーなど、SSHでログインできる環境向けのスクリプトです。1回の実行で次のことを行います。

  1. データベースを wp db export でダンプし、gzipで圧縮する
  2. WordPressのディレクトリ(wp-config.php と wp-content を含む)をtarでまとめる
  3. 圧縮ファイルが壊れていないかを確かめ、チェックサムを保存する
  4. 指定した日数より古いバックアップを削除する

前提は次のとおりです。

  • Linux(Ubuntu・Debianなど)で、root権限を使える
  • WP-CLI(wp コマンド)が入っている
  • WordPressのファイルは www-data ユーザーが所有している(環境に合わせて変更)

準備: WP-CLIでダンプできるか確かめる

wp db export は wp-config.php の接続情報を使って mysqldump を実行します。スクリプトに別途パスワードを書く必要はありません。まず手動で動くか確かめます。

sudo -u www-data wp db export - --path=/var/www/wordpress --single-transaction | head -n 5

ダンプの先頭行が表示されれば準備完了です。--single-transaction は mysqldump にそのまま渡され、InnoDBのテーブルをサイトを止めずに一貫した状態でダンプできます。

root のまま wp を実行すると、プラグインやテーマのコードをroot権限で動かすことになるため、WP-CLIは警告を出して止まります。--allow-root で回避するより、sudo -u www-data でファイルの所有者として実行するほうが安全です。

スクリプト本体

/usr/local/bin/wp-backup.sh として保存します。先頭の4つの変数を環境に合わせて書き換えてください。

#!/bin/bash
# /usr/local/bin/wp-backup.sh  WordPress のデータベースとファイルをバックアップする
set -euo pipefail

WP_DIR="/var/www/wordpress"          # WordPress のインストール先(wp-config.php がある場所)
BACKUP_ROOT="/var/backups/wordpress" # バックアップの保存先
KEEP_DAYS=14                         # 何日分残すか
WP_USER="www-data"                   # WordPress のファイルを所有するユーザー

STAMP="$(date +%Y%m%d_%H%M%S)"
DEST="${BACKUP_ROOT}/${STAMP}"

log() { echo "$(date '+%F %T') $*"; }

umask 077
mkdir -p "$DEST"
log "start: ${WP_DIR} -> ${DEST}"

# 1. データベース(wp-config.php の接続情報を使う。InnoDB なら公開したまま一貫したダンプになる)
sudo -u "$WP_USER" wp db export - --path="$WP_DIR" --single-transaction \
  | gzip > "${DEST}/db.sql.gz"
log "database: done"

# 2. ファイル(データベースの後に取る)
#    GNU tar は読み込み中にファイルが変わると終了コード 1 を返すので、1 は警告として扱う
tar -czf "${DEST}/files.tar.gz" \
  --exclude="$(basename "$WP_DIR")/wp-content/cache" \
  -C "$(dirname "$WP_DIR")" "$(basename "$WP_DIR")" || {
  rc=$?
  if [ "$rc" -ne 1 ]; then
    log "error: tar failed (exit ${rc})"
    exit "$rc"
  fi
  log "warning: some files changed while archiving"
}
log "files: done"

# 3. 壊れていないかの確認とチェックサム
gzip -t "${DEST}/db.sql.gz" "${DEST}/files.tar.gz"
(cd "$DEST" && sha256sum db.sql.gz files.tar.gz > SHA256SUMS)

# 4. 古い世代を削除
find "$BACKUP_ROOT" -mindepth 1 -maxdepth 1 -type d -mtime +"$KEEP_DAYS" -exec rm -rf {} +

log "finished: $(du -sh "$DEST" | cut -f1)"
sudo chmod 700 /usr/local/bin/wp-backup.sh
sudo /usr/local/bin/wp-backup.sh

ポイント

  • set -euo pipefail: どこかのコマンドが失敗した時点で止まります。pipefail があるので、wp db export が失敗したのに gzip だけ成功して空のファイルが残る、ということを防げます。
  • umask 077: 作ったバックアップをroot以外が読めないようにします。ダンプには、ユーザーのメールアドレスやパスワードのハッシュが含まれます。
  • データベースを先に、ファイルを後に取ります。逆にすると、データベースには記録があるのに画像ファイルが無い、というバックアップになることがあります。
  • --exclude でキャッシュ系プラグインの wp-content/cache を除いています。作り直せるものは省くと容量と時間を減らせます。
  • 古い世代は、作成日時から KEEP_DAYS 日を過ぎたディレクトリごと削除します。

WP-CLIが無い環境では、手順1を mysqldump に置き換えます。その場合、パスワードはコマンドラインではなく chmod 600 にしたオプションファイル(/root/.my.cnf の [client] 節)に書きます。

mysqldump --single-transaction --no-tablespaces --default-character-set=utf8mb4 \
  wordpress_db | gzip > "${DEST}/db.sql.gz"

cronで定期実行する

/etc/cron.d/wp-backup に次の1行を書くと、毎日3時15分にrootで実行されます(/etc/cron.d のファイルでは、時刻の後に実行ユーザーを書きます)。

15 3 * * * root flock -n /run/wp-backup.lock /usr/local/bin/wp-backup.sh >> /var/log/wp-backup.log 2>&1
  • flock -n は、前回の実行がまだ終わっていないときに二重に起動しないためのものです。
  • 出力はログファイルに追記されます。> ではなく >> にしないと、毎回上書きされます。
  • crontabの行に % を書くと改行として扱われます。日付の処理はスクリプトの中で行い、cronの行には書かないようにします。

ログが増え続けないよう、必要に応じてlogrotateの設定も追加してください。cronそのものの使い方はWordPressでサーバーのcronを設定する方法も参考になります。

復元の手順

チェックサムを確かめてから、データベースとファイルを戻します。ここでは 20261001_031500 の世代を戻す例です。

cd /var/backups/wordpress/20261001_031500
sha256sum -c SHA256SUMS

# データベース(現在の内容は上書きされる)
gunzip -c db.sql.gz | sudo -u www-data wp db import - --path=/var/www/wordpress

# ファイル(いったん別の場所に展開して中身を確かめてから入れ替える)
mkdir -p /tmp/wp-restore
tar -xzf files.tar.gz -C /tmp/wp-restore
sudo rsync -a --delete /tmp/wp-restore/wordpress/ /var/www/wordpress/
sudo chown -R www-data:www-data /var/www/wordpress

本番に戻す前に、検証用のサーバーやデータベースで一度試しておくと、いざというときに手順で迷いません。ドメインやパスが変わる環境へ戻す場合は、wp search-replace でURLを置き換えます。

運用の注意

  • このスクリプトの保存先は本番と同じサーバーです。ディスク故障やサーバーの乗っ取りに備え、別のサーバーやクラウドにも複製してください。考え方はWordPressの3-2-1バックアップルールで紹介しています。
  • バックアップの保存先のディスク容量を定期的に確認します。容量不足で失敗すると、set -e によりその時点で止まります。
  • 失敗に気づけるよう、結果を通知する仕組みを加えると安心です。WordPressのバックアップ結果をSlackに通知する方法で、このスクリプトに通知を足す方法を紹介しています。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲