WP-Cron(wp-cron.php):無効化とシステムcronの設定 | WordPressのパフォーマンス最適化

WordPressの Cronジョブは、特定の時刻や日付に予約されたタスクを自動で実行する機能です。このタスクはwp-cron.phpファイルを通じて実行され、WordPressはページが読み込まれるたびにこのファイルを呼び出して予約されたタスクを処理します。この方式は手軽ですが、トラフィックの多いサイトではパフォーマンスの低下を招くことがあります。

Ⅰ. WP-Cronの実行の流れとパフォーマンスの問題

WordPressはLinuxサーバーの伝統的なCronシステムを使わず、独自のCron機能である WP-Cronを提供しています。WP-Cronはwp-cron.phpファイルを通じて動作し、ⓐユーザーがサイトを訪れるたびに予約されたタスクがあるか確認して実行し、ⓑRank MathやWP Rocketなどのプラグインは独自に予約した定期的なタスクを実行します。

一方、トラフィックの多いサイトではwp-cron.phpが 過剰に頻繁に呼び出され、サーバーに過負荷をかけることがあります。特に、同時に複数のユーザーがアクセスすると重複したcronタスクが実行され、 CPU使用率の増加, 応答の遅延, ページ読み込み速度の低下 などの問題につながることがあります。

こうしたWP-Cronの構造的な限界はWordPressのパフォーマンスを低下させることがあり、特に 高い性能が求められるサイトやショッピングモール、ニュースポータル などでは致命的なボトルネックを引き起こすことがあります。

🔄 WP-Cronの実行方式と構造

WP-Cron
WP-Cron(wp-cron.php)
ⓐ ユーザー訪問時に予約タスクを確認
ⓑ プラグインの定期タスク(Rank Math, WP Rocket など)
WP-Cronのパフォーマンス問題
トラフィック依存
過剰な呼び出しによるサーバー過負荷
重複実行とボトルネック
WP-Cronの実行方式
トラフィックベースの仮想スケジューラー
予約タスクの実行の流れ
時間ベースではなく訪問ベースで実行

Ⅱ. WordPressのパフォーマンス最適化

  • ↳ WP-Cronの設定による最適化

WordPressのパフォーマンス最適化にはさまざまな方法があります。キャッシュやフロントエンド、データベースなどを最適化したあとに、WP-Cronの設定で改善する方法があります。

WordPress
パフォーマンス最適化
ブラウザキャッシュ
ページキャッシュ
フロントエンドの最適化
関連プラグイン(Autoptimize、ShortPixelなど)
データベースの整理
リビジョン/スパム/一時テーブルの削除
DB最適化プラグイン(WP-Optimize など)
WP-Cronの設定
WP-Cron(wp-cron.php)
ⓐ ユーザー訪問時に予約タスクを確認
ⓑ プラグインの定期タスク(Rank Math、WP Rocketなど)
WP-Cronのパフォーマンス問題
トラフィック依存
過剰な呼び出しによるサーバー過負荷
重複実行とボトルネック
WP-Cronの実行方式
トラフィックベースの仮想スケジューラー
予約タスクの実行の流れ
時間ベースではなく訪問ベースで実行

WordPressのページが読み込まれるたびに予約イベントが確認されるうえ、プラグインの定期タスクもあるため、非効率なWP-Cronを効率よく活用する必要があります。

1️⃣ WP-Cronのテスト

WP-CLIでcronタスクを確認すると、動作中のCronが実行されていることがわかります。Rank MathやWP Rocketなどのプラグインが、予約タスクを1日単位や分単位で実行していることが確認できます。

WP CLI- wp-cron event listコマンドで予約されたcronイベント一覧を確認_

2️⃣ WP-Cronの設定方法

WP-CronはWordPressの予約タスクを処理する仮想スケジューラーで、ユーザーの訪問時にwp-cron.phpが実行されます。しかしトラフィック頼みの実行は不安定で、過剰な呼び出しでサーバーに負荷をかけることがあるため、システムcronで補うのが一般的です。
必要に応じてwp-config.phpでDISABLE_WP_CRONを設定してWP-Cronをオフにし、Linuxのcronで定期実行する方法がおすすめです。

項目

WP-Cron無効化 + システムcronのみで実行

設定

WP-Cronをオフにし、システムcronからwp-cron.phpを実行

メリット

重複実行がなく、正確な時間ベースの実行が可能で、サーバー負荷も少ない

デメリット

一部のプラグイン機能が止まることがあり、設定ミスでタスクが抜け落ちるおそれ

おすすめの 状況

トラフィックが多く予約タスクも多いサイトに適している

ただし①の方式には、WP Rocketのようなキャッシュプラグインが1分ごとにPreLoad機能で訪問者が来る前にキャッシュを事前生成する機能が無効になるという欠点があります。

⚙️ wp-config.phpファイルの修正

WP_CRONを無効化する方法で設定できます。

# WP_CRONを無効化
define( 'DISABLE_WP_CRON', true );

WP_CRON_LOCK_TIMEOUTは、WP-Cronの実行中に ほかの実行の試みを防ぐ[時間ベースのロック]です。

# 5分は300、60分ごとの実行は3600
define('WP_CRON_LOCK_TIMEOUT', 300);

このような理由から、wp-config.phpファイルでWP-Cronを無効化するだけの方法よりも、無効化したあとに System Cron タスクを追加する方法をおすすめします。現在管理しているサーバーもこの方法で設定しました。

⚙️ Linuxサーバーでシステムcronを有効化[基本]

ドメインごとに有効化できます。

# 5分ごとに実行
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
# 30分ごとに実行
*/30 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
# 1時間ごとに実行
0 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
# 1日1回実行
0 3 * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1

上の4行はcrontabに登録する間隔別の例で、指定した時刻ごとにcurlが[wp-cron.php]のURLを呼び出すため、訪問者がいなくても予約タスクが実行されます。

# サーバーがローカルサーバーの場合
*/5 * * * * php /path/to/wordpress/wp-cron.php > /dev/null 2>&1

# 30分ごとに実行
*/30 * * * * php /path/to/wordpress/wp-cron.php > /dev/null 2>&1

# 1時間ごとに実行
0 * * * * php /path/to/wordpress/wp-cron.php > /dev/null 2>&1

# 1日1回実行
0 3 * * * php /path/to/wordpress/wp-cron.php > /dev/null 2>&1

WP-CLIをインストールしている場合は、希望する間隔で1つだけ設定できます。▼

# 5分ごとに実行
*/5 * * * * cd /sites/example.com/files/ && flock -n ~/.wp_cron.lock /usr/local/bin/wp cron event run --due-now --quiet

# 30分ごとに実行
*/30 * * * * cd /sites/example.com/files/ && flock -n ~/.wp_cron.lock /usr/local/bin/wp cron event run --due-now --quiet

# 1時間ごとに実行
0 * * * * cd /sites/example.com/files/ && flock -n ~/.wp_cron.lock /usr/local/bin/wp cron event run --due-now --quiet

# 1日1回実行
0 3 * * * cd /sites/example.com/files/ && flock -n ~/.wp_cron.lock /usr/local/bin/wp cron event run --due-now --quiet

サーバー内でWP-CLIが[--due-now]オプションで期限の来た予約タスクだけを実行する設定で、[flock -n]は前の実行が終わっていなければ新しい実行をスキップします。

⚙️ WP-CLIとシステムcron(1分)、cronタスクの重複防止

既定のWP_CRONは、作業量が多いと単に無視(スキップ)され、あとで再実行される仕組みです。既定のWP-Cronをオフにし、予約タスクに5分間のロックを保つよう設定して、システムcronとWP-Cronが重なって実行されるのを防ぎます。

define('DISABLE_WP_CRON', true);         // WP-Cronの自動実行をオフ
define('WP_CRON_LOCK_TIMEOUT', 300);     // 待機しない → 無視(スキップ)、予約タスクの実行中は5分間ロックを維持

/* That's all, stop editing! Happy publishing. */

システムcronにflock -nオプションを追加で設定し、システムcron側では即時終了で適用します。

# wp cronの設定: flock -n → 待機しない → 即時終了
*/1 * * * * cd /sites/example.com/files/ && flock -n ~/.wp_cron.lock /usr/local/bin/wp cron event run --due-now --quiet

上記のように設定した組み合わせの結果は、

  • WP内部の自動実行はオフ → 訪問者数に関係なく予約タスクを実行
  • システムcronが1分ごとに実行を試行 → 予約タスクがあれば実行される
  • ロックがかかると5分間は再実行されない → 重複実行を防止(実際にはflock -nの設定があるのでWP_CRON_LOCK_TIMEOUTはあえて必要ありません。)

重複実行の防止による実際の動作の流れは、

  1. 08:00 → システムcronがwp-cron.phpを呼び出し
    • 予約タスクAが実行 → 5分間のロックを設定
  2. 08:01 → システムcronが再び呼び出し
    • タスクAはロック中 → 実行されない
  3. 08:02~08:04 → 同じ
    • 08:05 → ロック解除 → 次の予約タスクがあれば実行

WPが自動で実行しない代わりに、システムが責任をもって実行するという点。 そしてWP_CRON_LOCK_TIMEOUTは 重複実行を防ぐ補助的な安全装置として動作するということです。

項目

WP_CRON_LOCK_TIMEOUT

flock -n

ロック方式

WordPress内部

システムレベル

ロックの場所

DBベース:wp_optionsのdoing_cron

システムファイルベース:~/.wp_cron.lock

待機の有無

❌ 待機しない → スキップ

❌ 待機しない → 即時終了

重複実行の防止

✅ 重複実行を防止

✅ 重複実行を防止

作業が終わったらWP-CLIコマンドで確認できます。以前と同じようにcronが正しく動いているか確認します。

wp cron event list
+-------------------------------------------+---------------------+-----------------------+---------------+
| hook                                      | next_run_gmt        | next_run_relative     | recurrence    |
+-------------------------------------------+---------------------+-----------------------+---------------+
| rocket_saas_pending_jobs                  | 2026-10-17 12:00:57 | now                   | 1 minute      |
| action_scheduler_run_queue                | 2026-10-17 12:00:57 | now                   | 1 minute      |
| action_scheduler_run_queue_rucss          | 2026-10-17 12:00:58 | now                   | 1 minute      |
| rocket_saas_on_submit_jobs                | 2026-10-17 12:00:58 | now                   | 1 minute      |
| rocket_preload_process_pending            | 2026-10-17 12:00:59 | now                   | 1 minute      |
| rocket_purge_time_event                   | 2026-10-17 12:16:59 | 15 minutes 8 seconds  | 1 hour        |
| wp_privacy_delete_old_export_files        | 2026-10-17 12:28:46 | 26 minutes 55 seconds | 1 hour        |
| wp_update_user_counts                     | 2026-10-17 20:15:52 | 8 hours 14 minutes    | 12 hours      |
| rocket_preload_revert_old_failed_rows     | 2026-10-17 20:17:59 | 8 hours 16 minutes    | 12 hours      |
| wp_version_check                          | 2026-10-17 20:28:34 | 8 hours 26 minutes    | 12 hours      |
| wp_update_plugins                         | 2026-10-17 20:58:34 | 8 hours 56 minutes    | 12 hours      |
| wp_update_themes                          | 2026-10-17 21:28:34 | 9 hours 26 minutes    | 12 hours      |
| recovery_mode_clean_expired_keys          | 2026-10-18 07:28:46 | 19 hours 26 minutes   | 1 day         |
| wp_privacy_personal_data_cleanup_requests | 2026-10-18 07:28:46 | 19 hours 26 minutes   | 1 day         |
| wp_scheduled_delete                       | 2026-10-18 08:15:52 | 20 hours 14 minutes   | 1 day         |
| delete_expired_transients                 | 2026-10-18 08:15:52 | 20 hours 14 minutes   | 1 day         |
| wp_scheduled_auto_draft_delete            | 2026-10-18 08:15:54 | 20 hours 14 minutes   | 1 day         |
| wp_delete_temp_updater_backups            | 2026-10-18 08:16:17 | 20 hours 14 minutes   | 1 week        |
| rocket_update_dynamic_lists               | 2026-10-18 08:16:57 | 20 hours 15 minutes   | 1 week        |
| rocket_saas_clean_rows_time_event         | 2026-10-18 08:16:57 | 20 hours 15 minutes   | 1 week        |
| rocket_performance_hints_cleanup          | 2026-10-18 08:16:58 | 20 hours 15 minutes   | 1 day         |
| rocket_preload_clean_rows_time_event      | 2026-10-18 08:26:57 | 20 hours 25 minutes   | 1 week        |
| rocket_database_optimization_time_event   | 2026-10-18 09:34:25 | 21 hours 32 minutes   | 1 day         |
| wp_site_health_scheduled_check            | 2026-10-19 07:28:46 | 1 day 19 hours        | 1 week        |
| rocket_remove_saas_failed_jobs            | 2026-10-19 08:16:58 | 1 day 20 hours        | 3 days        |
+-------------------------------------------+---------------------+-----------------------+---------------+

出力には登録されたフック名と次回の実行時刻、繰り返し間隔が表示され、[next_run_relative]列が[now]のタスクは次のcron実行時にすぐ処理されます。

Ⅲ. WP-Cronの予約タスクが実行されないとき

予約した時刻になればタスクが自動で実行されると思いがちですが、WP-Cronは時刻ではなく、ページリクエストが来たときにやることを確認します。午後2時に予約したタスクも、午後5時までリクエストがなければ5時の最初のリクエストで実行されます。

実行が遅れると、予約投稿は投稿一覧で[予約投稿に失敗](Missed schedule)と表示されます。[ツール › サイトヘルス]のステータスタブの[おすすめの改善]には[予定されたイベントが失敗しました]が表示されます。キャッシュのプリロードのようにプラグインが登録したタスクも、同じ理由で実行を待ちます。

予約タスクはページリクエスト、やることの確認、ループバックリクエストを経て[wp-cron.php]で実行され、このうち一つでも途切れると、時刻を過ぎても実行されません。

🧭 予約タスクが実行されるまで
解説ダイアグラム
🔍 状況
🌐
ページリクエスト
WordPressが動く訪問
✕ 実行されない
→
🔎
やることの確認
時刻を過ぎたタスクがあるか
✕ 確認しない
→
🔁
ループバックリクエスト
サーバー → 自分のアドレスの[wp-cron.php]
✕ 403
→
⚙️
タスクの実行
[wp-cron.php]が予約タスクを処理
✓ 実行
WordPressが動くリクエストが来ると、時刻を過ぎたタスクを確認し、サーバーが自分のアドレスの[wp-cron.php]を呼び出してタスクを処理します。
訪問がないか、ページキャッシュファイルで応答すると、WordPressが動かないため、時刻を過ぎたタスクも次のリクエストまで待ちます。
[DISABLE_WP_CRON]がtrueなら、リクエストが来てもやることを確認せず、システムcronがなければタスクを実行するところがありません。
[wp-cron.php]をブロックするセキュリティルールがあると、ループバックリクエストが403で返り、タスクは実行されません。

1️⃣ 訪問がないとき、またはページキャッシュが応答するとき

WP-CronはWordPressが動くリクエストでしかやることを確認しないため、訪問がない時間帯には時刻を過ぎたタスクがそのまま溜まります。訪問があってもページキャッシュファイルで応答するとWordPressが動かないので、結果は同じです。

WP Rocketのページキャッシュが有効なWordPressで、キャッシュされたトップページを開いたときは[wp-cron.php]の呼び出しが記録されませんでした。キャッシュされないURLを開くと同じ秒に呼び出しが記録され、溜まっていたタスク5つが実行されました。

溜まったタスクは、WP-CLIの一覧で[next_run_relative]が[now]の行だけに絞って確認できます。

wp cron event list --next_run_relative=now --fields=hook,next_run_gmt,next_run_relative
+----------------------------------+---------------------+-------------------+
| hook                             | next_run_gmt        | next_run_relative |
+----------------------------------+---------------------+-------------------+
| rocket_saas_pending_jobs         | 2026-10-17 14:49:57 | now               |
| action_scheduler_run_queue       | 2026-10-17 14:49:57 | now               |
| action_scheduler_run_queue_rucss | 2026-10-17 14:49:58 | now               |
| rocket_saas_on_submit_jobs       | 2026-10-17 14:49:58 | now               |
| rocket_preload_process_pending   | 2026-10-17 14:49:59 | now               |
+----------------------------------+---------------------+-------------------+

[now]は予定時刻をすでに過ぎたタスクで、この一覧コマンドもWordPressを読み込むため、溜まったタスクがあれば終わった瞬間に[wp-cron.php]を呼び出します。同じコマンドをすぐもう一度実行すると、さっき見えていたタスクは一覧から消えています。

原因を直す前に溜まったタスクを先に処理するには、WP-CLIで期限を過ぎたタスクだけをすぐ実行します。

wp cron event run --due-now
Executed the cron event 'rocket_saas_pending_jobs' in 0.005s.
Executed the cron event 'action_scheduler_run_queue' in 0.006s.
Executed the cron event 'action_scheduler_run_queue_rucss' in 0.006s.
Executed the cron event 'rocket_saas_on_submit_jobs' in 0.005s.
Executed the cron event 'rocket_preload_process_pending' in 0.007s.
Success: Executed a total of 5 cron events.

このコマンドはHTTPリクエストなしでサーバー内でタスクを実行します。訪問に関係なく決まった間隔で処理するには、同じコマンドをシステムcronに登録します。

2️⃣ DISABLE_WP_CRONだけを有効にしてシステムcronがないとき

[DISABLE_WP_CRON]をtrueにすると、ページリクエストが来てもWP-Cronはやることを確認しません。公式ドキュメントも、先にシステムのタスクスケジューラーに登録してからこの定数を入れる順番で案内しており、登録せずに定数だけを入れると予約タスクを実行するところがなくなります。

定数を入れた状態で1分少し先に予約した投稿は、時刻を過ぎても[予約済み]のままで、投稿一覧の日付欄には[予約投稿に失敗]と表示されました。その間、[wp-cron.php]の呼び出しは一度も記録されませんでした。

定数が有効かどうかは[wp cron test]で確認できます。

wp cron test
Error: The DISABLE_WP_CRON constant is set to true. WP-Cron spawning is disabled.

このエラーが出たら、システムcronに[wp-cron.php]を呼び出す行か[wp cron event run]を実行する行があるか確認します。サイトのアカウントのcrontabが空なら、次のように表示されます。

crontab -l
no crontab for example

行がなければシステムcronを登録し、登録できない環境なら[DISABLE_WP_CRON]の行を消してWP-Cronをまた使います。

3️⃣ サーバーのループバックリクエストがブロックされたとき

WP-Cronはやることがあると、サーバーが自分のサイトアドレスの[wp-cron.php]にリクエストを送ってタスクを実行し、このリクエストがループバックリクエストです。[wp-cron.php]をブロックするセキュリティルールがあると、ループバックリクエストが403で返り、タスクは実行されません。

Nginx + Apache構成のサーバーで[wp-cron.php]を127.0.0.1からしか開けないように制限すると、ループバックリクエストが403でブロックされました。サーバーが自分のドメインに送ったリクエストはパブリックIPから入ってくるためで、[wp cron test]も同じステータスコードを返します。

wp cron test
Error: WP-Cron spawn returned HTTP status code: 403 Forbidden

タスクが5分以上溜まった状態で[サイトヘルス]画面を開くと、[おすすめの改善]にループバックの警告と予定されたイベントの失敗が一緒に表示されました。

WP-Cronのループバックリクエストが403でブロックされ、サイトヘルスのステータスタブに予定されたイベントの失敗とループバックリクエストの警告が表示された画面

ルールを消すと[wp cron test]はまた成功しました。ルールを残す必要があるなら、システムcronからWP-CLIで実行します。WP-CLIの実行はHTTPリクエストを経由しないため、同じルールがある状態でも溜まったタスクが処理されました。

🔢 FAQ & おすすめコンテンツ

更新確認のタスクである[wp_version_check]、[wp_update_plugins]、[wp_update_themes]は、テストサイトでは12時間間隔でした。ゴミ箱を空にする処理([wp_scheduled_delete])と期限切れのトランジェントの削除は1日、サイトヘルスのチェックは1週間間隔で登録されていました。ゴミ箱を空にする処理は、ゴミ箱に入ってから30日(初期値)が過ぎた投稿とコメントを完全に削除するタスクで、WP-Cronが実行されないとこれらのタスクも予定の時刻に実行されません。

プラグインに含まれるジョブキューライブラリAction Schedulerが待機中のジョブを処理するフックで、テストサイトでは1分間隔で登録されていました。Action Schedulerの公式FAQは、このキューが基本的にWP-Cronと管理画面リクエストの終わり([shutdown]フック)で開始されると案内しています。システムcronなしで[DISABLE_WP_CRON]だけを有効にしたテストサイトでは、この行も予約投稿と一緒に[now]のまま残りました。

公式ドキュメントでは、[wp-config.php]で[ALTERNATE_WP_CRON]定数をtrueにする代替方式が案内されています。実行するタスクがあると、訪問者のGETリクエストを[doing_wp_cron]の値を付けた同じURLにリダイレクトします。このとき[wp-cron.php]は元のリクエストの中で実行され、ループバックリクエストを経由しません。同じドキュメントは、この方式がWordPressの標準動作ではないためリスクがあると案内しており、システムcronを登録できるならシステムcronを優先して使います。

🧭 WordPressの予約タスク おすすめコンテンツ 記事7・参照4
🗂️ WordPressの予約タスク
📄 WP-Cron(wp-cron.php) 📄 wp-config.phpの基本設定 📄 WordPressサイトヘルス
📋 crontabの設定 📄 Linux niceコマンド
📋 WP CLI:インストールと設定 📄 同期パターンを探す:WP-CLI
📡 About Cron 📡 WP Cronイベント 📡 cronスケジューリングを理解する 📡 WP-Cronをシステムのタスクスケジューラーに接続する
検索結果がありません。

ℹ️ 提携について
当サイトのコンテンツにはアフィリエイトリンクが含まれています。訪問者がこのリンクを通じて商品やサービスを購入すると、当サイトは販売元から手数料を受け取ります。この過程において、購入者が支払う金額(イベント割引適用で金額が下がります↓)は上昇しません。掲載されている価格・割引・在庫情報は作成時点のものであり、実際とは異なる場合がありますので、ご購入前に販売元にて最終確認をお願いいたします。商品の選定および評価は独自の基準に基づいて行われており、手数料の支払いの有無は紹介順や評価内容に影響を与えません。

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

人間であることを証明してください: 8   +   8   =