2026年6月25日

2026年6月25日

cronでWordPressのバックアップを自動化する|DBとファイルを毎日保存するスクリプト

WordPress のバックアップは、プラグインを使わなくても Linux の cron とシェルスクリプトで自動化できます。この記事では、次の2つを毎日決まった時刻に作るスクリプトを用意し、cron に登録します。

  • データベース:投稿・固定ページ・設定・ユーザーなど。mariadb-dump(MySQL では mysqldump)で SQL ファイルとして書き出す
  • ファイル:wp-config.php、テーマ、プラグイン、アップロードした画像(wp-content)など。tar でまとめる

スクリプトは 2026年10月時点の MariaDB 11 の公式 Docker イメージ(Ubuntu ベース、bash 5.2)で、バックアップの作成、古いファイルの削除、データベースに接続できないときの中断を確認しています。VPS や専用サーバーなど、root(または sudo)で cron を設定できるサーバーを前提にしています。

用意するもの

  • WordPress が動いている Linux サーバーへの SSH 接続と sudo 権限
  • WordPress のデータベース名(wp-config.php の DB_NAME)
  • バックアップの保存先(例:/var/backups/wordpress)。空き容量に余裕があること

バックアップ用のデータベースユーザーを作る

wp-config.php のユーザーをそのまま使うこともできますが、読み取りに必要な権限だけを持つユーザーを別に作っておくと、パスワードが漏れたときの影響を小さくできます。MariaDB / MySQL に管理者で接続して実行します。

CREATE USER 'wpbackup'@'localhost' IDENTIFIED BY '長く推測されにくいパスワード';
GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT ON wordpress.* TO 'wpbackup'@'localhost';

wordpress の部分は、実際のデータベース名に置き換えます。

接続情報をファイルに分けて置く

パスワードをコマンドの引数(-p パスワード)に書くと、ps コマンドなどでほかのユーザーから見える場合があります。接続情報は root だけが読めるファイルに書き、--defaults-extra-file で読み込ませます。

sudo nano /root/.wp-backup.cnf
[client]
user=wpbackup
password=長く推測されにくいパスワード
host=localhost
sudo chmod 600 /root/.wp-backup.cnf

バックアップスクリプトを作る

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

#!/bin/bash
# WordPress のデータベースとファイルをバックアップし、古いバックアップを削除する
set -euo pipefail

WP_DIR="/var/www/html"                # WordPress のインストール先
BACKUP_DIR="/var/backups/wordpress"   # バックアップの保存先
DB_NAME="wordpress"                   # データベース名(wp-config.php の DB_NAME)
DB_CNF="/root/.wp-backup.cnf"         # データベースの接続情報を書いたファイル
KEEP_DAYS=14                          # この日数より古いバックアップを削除する

STAMP=$(date +%Y%m%d-%H%M%S)
umask 077                             # 作るファイルを root だけが読めるようにする
mkdir -p "$BACKUP_DIR"

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

# 前回のバックアップがまだ動いていれば、今回は実行しない
exec 9> "$BACKUP_DIR/.lock"
flock -n 9 || { log "前回のバックアップが実行中のため終了"; exit 1; }

# 途中で失敗したら、作りかけのファイルを消して終了コードを記録する
cleanup() {
  local rc=$?
  if [ "$rc" -ne 0 ]; then
    rm -f "$BACKUP_DIR/db-$STAMP.sql.gz" "$BACKUP_DIR/files-$STAMP.tar.gz"
    log "失敗しました(終了コード $rc)"
  fi
}
trap cleanup EXIT

# MariaDB 11 以降は mariadb-dump、MySQL は mysqldump
DUMP=$(command -v mariadb-dump || command -v mysqldump)

log "データベースのバックアップ開始"
"$DUMP" --defaults-extra-file="$DB_CNF" \
  --single-transaction --quick --no-tablespaces \
  --default-character-set=utf8mb4 "$DB_NAME" \
  | gzip > "$BACKUP_DIR/db-$STAMP.sql.gz"

log "ファイルのバックアップ開始"
# tar は読み取り中にファイルが変わると終了コード 1 を返す。これは警告として扱う
tar -czf "$BACKUP_DIR/files-$STAMP.tar.gz" \
  -C "$(dirname "$WP_DIR")" "$(basename "$WP_DIR")" \
  || { rc=$?; [ "$rc" -eq 1 ] || exit "$rc"; }

# 圧縮ファイルが壊れていないか確認する
gzip -t "$BACKUP_DIR/db-$STAMP.sql.gz" "$BACKUP_DIR/files-$STAMP.tar.gz"

# 古いバックアップを削除する
find "$BACKUP_DIR" -maxdepth 1 -type f \
  \( -name 'db-*.sql.gz' -o -name 'files-*.tar.gz' \) \
  -mtime +"$KEEP_DAYS" -delete

log "完了: db-$STAMP.sql.gz files-$STAMP.tar.gz"

スクリプトのポイント

  • set -euo pipefail により、途中のコマンドが失敗したらそこで止まります。pipefail があるので、mariadb-dump が失敗したのに gzip だけ成功して「空のバックアップ」ができる、ということを防げます
  • --single-transaction は、InnoDB のテーブルをロックせずに、ある時点のそろった内容で書き出すオプションです。WordPress の標準テーブルは InnoDB なので、サイトを止めずにバックアップできます
  • --no-tablespaces は、MySQL 8.0.21 以降で PROCESS 権限のないユーザーが実行したときのエラーを避けるために付けています
  • flock で二重実行を防ぎます。データが大きく、前回のバックアップが終わらないうちに次の実行時刻が来ても重なりません
  • 失敗したときは作りかけのファイルを削除し、ログに終了コードを残します
  • find -mtime +14 は、最終更新から15日以上たったファイルを削除します。何世代残すかは、保存先の容量と相談して KEEP_DAYS で決めます

WP-CLI が使える場合

WP-CLI が入っているサーバーでは、データベースの部分を wp db export に置き換えることもできます。接続情報は wp-config.php から読み込まれるので、.cnf ファイルは不要です。

sudo -u www-data wp db export - --path=/var/www/html | gzip > "$BACKUP_DIR/db-$STAMP.sql.gz"

- はファイルではなく標準出力に書き出す指定です。www-data は Web サーバーの実行ユーザー(Debian / Ubuntu の場合)なので、環境に合わせて変えてください。

手動で動かして確かめる

cron に登録する前に、手動で実行して結果を確かめます。

sudo chmod 700 /usr/local/bin/wp-backup.sh
sudo /usr/local/bin/wp-backup.sh
ls -l /var/backups/wordpress

成功すると、次のように表示され、保存先に2つのファイルができます。

2026-10-29 17:29:39 データベースのバックアップ開始
2026-10-29 17:29:39 ファイルのバックアップ開始
2026-10-29 17:29:39 完了: db-20261029-172939.sql.gz files-20261029-172939.tar.gz

中身も確認しておきます。

# データベース:テーブル作成の行が出てくるか
zcat /var/backups/wordpress/db-*.sql.gz | grep -m 5 'CREATE TABLE'

# ファイル:wp-config.php が含まれているか
tar -tzf /var/backups/wordpress/files-*.tar.gz | grep wp-config.php

データベース名やパスワードが間違っていると、次のようにエラーが表示されて止まり、作りかけのファイルは削除されます。

mariadb-dump: Got error: 1044: "Access denied for user 'wpbackup'@'localhost' to database 'nodb'" when selecting the database
2026-10-29 17:29:39 失敗しました(終了コード 2)

cronに登録する

sudo crontab -e で root の crontab を開き、次の1行を追加します。毎日3時30分に実行し、結果をログファイルに追記します。

30 3 * * * /usr/local/bin/wp-backup.sh >> /var/log/wp-backup.log 2>&1

5つの欄は、左から「分 時 日 月 曜日」です。

書き方 実行するタイミング
30 3 * * * 毎日 3:30
0 */6 * * * 6時間ごと(0:00、6:00、12:00、18:00)
0 4 * * 0 毎週日曜日の 4:00

crontab -e の代わりに、/etc/cron.d/ にファイルを置く方法もあります。この場合は時刻のあとに実行するユーザー名を書きます。

# /etc/cron.d/wp-backup
30 3 * * * root /usr/local/bin/wp-backup.sh >> /var/log/wp-backup.log 2>&1

Debian / Ubuntu では、/etc/cron.d/ のファイル名に . を含めると読み込まれません(英数字・-・_ だけにします)。

cronで動かすときの注意

  • cron の環境変数 PATH は短く、ログイン時とは違います。スクリプトやコマンドは /usr/local/bin/wp-backup.sh のようにフルパス(/ から始まるパス)で書きます
  • crontab の行の中で % を使うと改行として扱われます。date +%F などを crontab の行に直接書く場合は \% とします(この記事では日付の処理をスクリプトの中で行っているので不要です)
  • サーバーの時刻帯は timedatectl で確認できます。UTC になっている場合、30 3 * * * は日本時間の 12:30 です

実行されたか確認する

まずはスクリプトのログを確認します。

tail -n 20 /var/log/wp-backup.log

ログに何も書かれていない場合は、cron がスクリプトを起動したかどうかを cron 自体のログで確かめます。

# Debian / Ubuntu
journalctl -u cron --since today

# RHEL / AlmaLinux / Rocky Linux
journalctl -u crond --since today

rsyslog が入っている環境では、Debian / Ubuntu は /var/log/syslog、RHEL 系は /var/log/cron にも記録されます。

/var/log/wp-backup.log は少しずつ大きくなるので、長く運用する場合は logrotate の対象にします。

バックアップから戻す

復元は、データベースとファイルを同じ日時のもので戻します。作業前に、今の状態のバックアップも取っておくと安全です。

# データベースを戻す(接続情報は書き込み権限のあるユーザーのものを使う)
zcat /var/backups/wordpress/db-20261029-172939.sql.gz | sudo mariadb wordpress

# ファイルを戻す(/var/www/html に展開される)
sudo tar -xzf /var/backups/wordpress/files-20261029-172939.tar.gz -C /var/www

MySQL の場合は mariadb を mysql に置き換えます。バックアップ用に作った wpbackup ユーザーは読み取り権限しかないので、復元には使えません。

注意点

  • 保存先を分ける:同じサーバーのディスクにだけ保存していると、サーバーの故障や乗っ取りでバックアップも失われます。rsync やオブジェクトストレージへのコピーを組み合わせ、別の場所にも置いてください
  • 容量:uploads が大きいサイトでは、毎日ファイル全体を固めると容量を圧迫します。保存日数を減らすか、ファイルは差分バックアップ(rsync など)にする方法があります
  • 復元の練習:バックアップは戻せて初めて役に立ちます。テスト環境で実際に復元してみて、手順と所要時間を確認しておきます
  • バックアップの中身は機密情報:wp-config.php やユーザー情報が含まれます。保存先のパーミッションを root だけに絞り、外部に置く場合は暗号化も検討します

まとめ

  • データベースは mariadb-dump(mysqldump)に --single-transaction を付けて書き出し、ファイルは tar で固める
  • 接続情報は root だけが読めるファイルに置き、--defaults-extra-file で読み込む
  • set -euo pipefail、flock、失敗時の後片付けで、空のバックアップや二重実行を防ぐ
  • cron にはフルパスで登録し、スクリプトのログと journalctl で実行を確認する
  • 別の場所への保存と、復元の練習も合わせて行う

関連記事:

お気軽にご相談ください

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