2026年8月13日
2026年8月13日
WordPressのWP-Cronが動作しない問題を解決する方法
はじめに
WordPressで予約投稿が指定した時刻に公開されない・wp_schedule_eventで登録したタスクが実行されない・DISABLE_WP_CRON=trueにしたらメール通知・自動更新・トランジェントの削除が止まった・WP-Cronがサイトへのアクセス時にしか動かないためアクセスの少ない時間帯にタスクが溜まる・同じCronイベントが二重登録されているといった問題は、WP-CronとシステムCronを正しく組み合わせることで解決できます。
症状・原因
- WP-CronはHTTPリクエストをフックにして動作するため、アクセスがないと実行されない
wp_schedule_eventでイベントを登録する際に重複チェック(wp_next_scheduled)をしていないDISABLE_WP_CRON=trueに設定したがサーバーCronを設定していない- タイムゾーン設定のズレにより予約投稿の時刻がずれている
解決手順
ステップ1:WP-Cronの状態を診断する
# 登録されているCronイベントを確認
wp cron event list --format=table
# 次回実行時刻を確認
wp cron event list --format=table | grep -v "^+"
# 期限切れイベント(実行されるべきだったが未実行)を確認
wp cron event list --format=table | awk 'NR>2 {print $3, $1}' | sort
# Cronスケジュール一覧を確認
wp cron schedule list --format=table
# WP-Cronが有効かどうか確認
wp eval "echo defined('DISABLE_WP_CRON') && DISABLE_WP_CRON ? 'disabled' : 'enabled';"
# 手動でCronを実行
wp cron event run --due-now
ステップ2:WP-Cronイベントを正しく登録する
// プラグイン有効化時にCronイベントを登録
register_activation_hook(__FILE__, function(): void {
if (!wp_next_scheduled('my_hourly_task')) { // 重複チェック必須
wp_schedule_event(time(), 'hourly', 'my_hourly_task');
}
});
// プラグイン無効化時にCronイベントを削除
register_deactivation_hook(__FILE__, function(): void {
$timestamp = wp_next_scheduled('my_hourly_task');
if ($timestamp) {
wp_unschedule_event($timestamp, 'my_hourly_task');
}
// または全スケジュールを一括削除
wp_clear_scheduled_hook('my_hourly_task');
});
// Cronコールバックを登録
add_action('my_hourly_task', function(): void {
error_log('[Cron] my_hourly_task executed at ' . current_time('Y-m-d H:i:s'));
// 実際の処理
do_something_important();
});
ステップ3:カスタムCronスケジュールを追加する
// カスタム実行間隔を追加(5分・15分・週2回など)
add_filter('cron_schedules', function(array $schedules): array {
$schedules['every_5_minutes'] = [
'interval' => 5 * MINUTE_IN_SECONDS,
'display' => '5分ごと',
];
$schedules['every_15_minutes'] = [
'interval' => 15 * MINUTE_IN_SECONDS,
'display' => '15分ごと',
];
$schedules['twice_weekly'] = [
'interval' => 3.5 * DAY_IN_SECONDS,
'display' => '週2回',
];
return $schedules;
});
// カスタムスケジュールでイベントを登録
add_action('init', function(): void {
if (!wp_next_scheduled('my_5min_task')) {
wp_schedule_event(time(), 'every_5_minutes', 'my_5min_task');
}
});
ステップ4:サーバーCronでWP-Cronを確実に実行する
# wp-config.php に追加してWP-Cronを無効化
# define('DISABLE_WP_CRON', true);
# define('WP_CRON_LOCK_TIMEOUT', 60); // 60秒のロック
# サーバーのCrontabを設定(毎分実行)
crontab -e
# 以下を追加:
# * * * * * php /var/www/html/wp-cron.php > /dev/null 2>&1
# または WP-CLI を使用:
# * * * * * cd /var/www/html && wp cron event run --due-now --quiet
# WP-CLIがない場合はcurlで呼び出す:
# * * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
// functions.php: Cronの実行をログに記録
add_action('wp_loaded', function(): void {
if (defined('DOING_CRON') && DOING_CRON) {
error_log('[WP-Cron] Running at ' . current_time('Y-m-d H:i:s')
. ' (memory: ' . round(memory_get_usage(true) / 1024 / 1024, 2) . 'MB)');
}
});
ステップ5:Cronの問題をデバッグする
// 特定のCronイベントの次回実行時刻を確認
$next = wp_next_scheduled('my_hourly_task');
if ($next) {
echo '次回実行: ' . get_date_from_gmt(date('Y-m-d H:i:s', $next)) . PHP_EOL;
} else {
echo 'スケジュールされていません' . PHP_EOL;
}
// 全Cronイベントをデバッグ出力
$cron_array = _get_cron_array();
foreach ($cron_array as $timestamp => $hooks) {
$time_diff = $timestamp - time();
foreach ($hooks as $hook => $events) {
$status = $time_diff < 0 ? '【期限切れ ' . abs($time_diff) . '秒前】' : '(' . $time_diff . '秒後)';
error_log(sprintf('[Cron] %s %s: %s', date('Y-m-d H:i:s', $timestamp), $status, $hook));
}
}
// Cronイベントを即時実行してテスト
wp_schedule_single_event(time() - 1, 'my_hourly_task');
spawn_cron();
注意事項
DISABLE_WP_CRON=trueに設定する場合は必ずサーバーCronの設定もセットで行ってください。設定しないと予約投稿・自動更新・セッションクリーンアップなどWordPressの重要な処理が停止します- WP-Cronはマルチサイト環境では各サイト独立して動作します。サーバーCronを設定する場合はすべてのサイトのURLを指定する必要があります
まとめ
WordPress WP-Cron問題の解決は①wp cron event listでイベント一覧・次回実行時刻・期限切れを確認・wp cron event run --due-nowで手動実行・DISABLE_WP_CRONの設定値を確認、②register_activation_hookでイベントを登録・wp_next_scheduledで重複チェックを必ず実施・register_deactivation_hookでwp_clear_scheduled_hookによりクリーンアップ、③cron_schedulesフィルターで5分・15分などカスタム間隔を追加・initフックで重複チェック付きで登録・MINUTE_IN_SECONDS/DAY_IN_SECONDS定数を活用、④DISABLE_WP_CRON=trueにしてサーバーCrontabで毎分wp cron event run --due-nowを実行・DOING_CRON定数でCron実行をログに記録・メモリ使用量も監視、⑤wp_next_scheduledで次回実行時刻を確認・_get_cron_array()で全イベントをデバッグ・wp_schedule_single_eventとspawn_cron()でテスト実行の手順で解決します。