• WordPressのWP-Cronが動かないときは登録、呼び出し、処理本体を分けて調べる

WordPressのWP-Cronが動かないときは登録、呼び出し、処理本体を分けて調べる

公開日: 執筆:佐藤

WordPressの予約投稿や定期処理が動かないときは、WP-Cronを一つの機能として調べません。イベントが登録されているか、期限を過ぎたイベントをWordPressが呼び出せるか、呼び出された処理が最後まで動くかの三段階に分けます。

WP-Cronは、指定した時刻にOSが必ず起動するcronとは違います。通常はサイトへのアクセスをきっかけに期限を確認し、wp-cron.phpへ別のHTTP要求を送って処理します。予定時刻は実行を始められる最初の時刻であり、その秒に動く保証ではありません。

WP-Cronはアクセス時に期限を過ぎたイベントを確認する

WordPress 3.5.1のcron処理は、保存されたイベントの時刻を調べ、期限を過ぎたものがあれば、サイト自身のwp-cron.phpへHTTP要求を送ります。通常のページ表示を処理し終わるまで待たない方法で呼び出すため、訪問者の要求と定期処理を分けています。

wp_schedule_event()の説明も、指定時刻を過ぎたあと、サイトへアクセスがあったときに登録したactionが動くと説明しています。アクセスが少ないサイトでは、予定時刻から次のアクセスまで処理が始まらない場合があります。

したがって、「毎日午前9時」は、OSのcronと同じ厳密な開始時刻ではありません。午前9時を過ぎた最初のアクセスで確認され、さらにwp-cron.phpの呼び出しと処理が必要です。時刻どおりの実行が業務上必要なら、WP-Cronの標準呼び出しだけへ任せるかを先に判断します。

イベントが登録されているかを先に確認する

定期処理は、wp_schedule_event()へ最初の実行時刻、繰り返し間隔、hook名、必要な引数を渡して登録します。標準の繰り返し間隔はhourly、twicedaily、dailyです。独自の間隔はcron_schedules filterで追加できます。

次は一時間ごとのイベントを登録する仕組みだけを示す仮例です。

if ( ! wp_next_scheduled( 'satolab_hourly_check' ) ) {
    wp_schedule_event( time(), 'hourly', 'satolab_hourly_check' );
}

satolab_hourly_checkは実在するプラグインのhookではありません。wp_next_scheduled()で同じhookと引数の次回予定を確認してから登録し、ページを読むたびに同じイベントを増やさないための例です。

予定が存在しなければ、呼び出し時刻を調べる前に、登録処理が実行された条件を確認します。プラグインの有効化時だけ登録する設計なら、有効化処理が走ったか、hook名と繰り返し間隔が正しいかを見ます。存在する予定を何度も追加しても、元の登録条件は直りません。

呼び出しが止まる条件を確認する

イベントが登録済みなのに期限を過ぎたままなら、WordPressがwp-cron.phpを呼び出せるかを調べます。WordPress 3.5.1は、サイト自身へwp_remote_post()で要求を送ります。サーバーが自分の公開URLへ接続できない、名前解決やSSLで失敗する、アクセス制限がwp-cron.phpを止める場合は、この段階で処理が始まりません。

wp-config.phpでDISABLE_WP_CRONが真に設定されていると、通常のアクセスをきっかけにした呼び出しは行われません。この定数は、サーバー側のcronなど、別の方法でwp-cron.phpを呼ぶときに使います。外部の呼び出しを用意せず、定数だけを追加すれば、登録イベントは動かなくなります。

確認するのは、定数の有無だけではありません。WordPressアドレスとサイトアドレス、HTTP要求の失敗、サーバーのアクセス制限、wp-cron.phpの応答を分けます。公開画面が表示できることと、サーバーから同じサイトへHTTP要求を送れることは別です。

呼び出し成功と処理完了を同じにしない

wp-cron.phpが呼び出されても、登録したコールバックでPHPエラーが起きたり、外部サービスへの接続で止まったりすれば、目的の処理は完了しません。WP-Cronの呼び出し確認だけで、「メール送信が完了した」「データが更新された」と判断してはいけません。

処理本体には、開始、対象件数、完了、失敗理由を確認できる記録を残します。ただし、パスワード、メール本文、個人情報をそのままログへ出しません。公開画面へエラーを表示せず、運用担当が読める場所でログを確認します。

重い処理を一つのイベントへ詰め込むと、途中で失敗したときの範囲が広がります。対象を少数ずつ処理し、再実行しても同じデータを重ねて作らない設計にします。WP-Cronが動いたかと、業務上の結果が一度だけ正しく作られたかを分けます。

外部cronへ切り替えるなら呼び出し元を一つにする

アクセスが少なく、予定時刻に近い実行が必要なら、サーバー側のcronからwp-cron.phpを定期的に呼ぶ方法を検討します。呼び出しコマンド、間隔、実行ユーザー、タイムアウト、失敗通知は、利用するサーバーに合わせて決めます。

外部cronを使う場合は、その呼び出しが実際に動くことを確認してからDISABLE_WP_CRONを設定します。標準の呼び出しと外部cronを両方、意図なく動かしたままにせず、どちらが起動責任を持つかを記録します。

サーバー会社や制作会社へ設定を頼むときは、wp-cron.phpを呼ぶ間隔だけでなく、対象サイト、コマンド、実行ユーザー、ログ、失敗時の連絡、契約終了時の引継ぎを確認します。WordPress内のイベント登録と、サーバー側の起動設定は別の所有物です。

調査は三段階の記録を一つずつ取る

最初に、動かなかった処理のhook名、予定時刻、引数を確認します。次に、その予定が登録されているかを見ます。登録済みなら、期限を過ぎたあとにwp-cron.phpが呼ばれたかを確認し、最後にコールバックの開始と完了を調べます。

段階 確認する事実 次に調べるもの
登録 hook、次回時刻、間隔、引数が存在するか 登録条件と重複防止
呼び出し 期限後にwp-cron.phpへ要求が届いたか アクセス、HTTP要求、DISABLE_WP_CRON
処理本体 コールバックが開始し完了したか PHPエラー、外部接続、処理対象、再実行

予約投稿だけが遅れるのか、同じ時刻帯の定期処理も止まるのかも分けます。一つのhookだけなら登録か処理本体を、複数の期限切れイベントが残るなら呼び出しを先に疑えます。

最初の一手は、wp-cron.phpを何度も開くことではありません。動かなかった一件について、hook、予定時刻、登録の有無を記録してください。その後で、呼び出しと処理本体を順に確認します。

戻る