問題の概要
午前9時に投稿をスケジュールしました。9時になっても、投稿は「スケジュール済み」のステータスのまま — 通知もなく、エラーもなく、ただ沈黙。管理画面を更新しても変わりません。投稿が詰まっています。
このような状況では、ほぼ毎回原因は同じです:wp-cronです。
根本原因
WordPressは実際のシステムcronを使用していません。代わりに、WP-Cron(wp-cron.php)という独自の疑似スケジューラを持っており、投稿の公開、メール送信、プラグインのジョブ、その他の時間ベースのタスクを処理します。問題は?誰かがサイトを訪問したときにしか実行されないという点です。訪問者がいなければ、cronも動きません。
この設計はアクセスの多いサイトでは問題なく機能します。しかし、以下のような状況では破綻します:
DISABLE_WP_CRONがwp-config.phpでtrueに設定されている — マネージドホストや「パフォーマンス最適化」ガイドに従った後に非常によく見られます- アクセスの少ないサイト — 1日50人しか訪問しないブログは、cronのトリガーが数時間おきになる場合があります
- Nginxの設定やファイアウォールルールがHTTPループバックリクエストをブロックしている(サーバーが自分自身を呼び出せない)
- プラグインが致命的なPHPエラーをスローし、cronが実行される前に処理が終了してしまう
ステップ1:DISABLE_WP_CRONが設定されているか確認する
wp-config.phpを開いて、以下の行を検索します:
define('DISABLE_WP_CRON', true);
見つかりましたか?それが原因です。その行を完全に削除するか、falseに変更してください:
define('DISABLE_WP_CRON', false);
ファイルを保存します。2〜3分後にスケジュールされたテスト投稿を作成して、時間通りに公開されるか確認してください。
ステップ2:WP-Cronを手動でテストする
最悪の事態を想定する前に、wp-cronを直接トリガーして何が起きるか確認しましょう:
# WP-CLI経由(推奨)
wp cron event run --due-now
# またはブラウザでこのURLに直接アクセス
https://yourdomain.com/wp-cron.php?doing_wp_cron
WP-CLIからエラーが出るか、そのURLから200以外のレスポンスが返る場合は、ループバックリクエストが何かによってブロックされています。
ループバック接続の確認
# サーバー自体からこのコマンドを実行
curl -I https://yourdomain.com/wp-cron.php
接続が拒否されたりタイムアウトになる場合、サーバーが自分自身へHTTPリクエストを送信できません。これは特定のVPSセットアップや、厳格なファイアウォールルールを持つリバースプロキシの後ろでよく見られます。
ステップ3:WP-Cronを実際のシステムcronに置き換える
訪問者によってトリガーされるcronは、設計上信頼性がありません。スケジュール投稿に依存する本番サイトでは、これを廃止して代わりに実際のcronジョブを使用してください。DISABLE_WP_CRONをtrueに設定し、システムcronを自分で設定しましょう。
3a. 組み込みWP-Cronを無効化する
// wp-config.php内
define('DISABLE_WP_CRON', true);
3b. システムcronジョブを追加する
crontabを編集します:
crontab -e
以下のいずれかを選択してください — 5分ごとの実行がレスポンスとサーバー負荷のバランスとして最適です:
# オプション1:直接PHP(最もシンプル)
*/5 * * * * php /var/www/html/wp-cron.php > /dev/null 2>&1
# オプション2:WP-CLI(より信頼性が高く、マルチサイトに対応)
*/5 * * * * cd /var/www/html && wp cron event run --due-now --quiet
# オプション3:wget/curl(PHPのパスが異なる場合に便利)
*/5 * * * * wget -q -O - https://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
cPanelの場合
cPanel → Cron Jobsに移動し、間隔を5分ごとに設定して以下を入力します:
php /home/yourusername/public_html/wp-cron.php > /dev/null 2>&1
ステップ4:詰まっているスケジュール済み投稿を手動で公開する
「スケジュール済み」状態で詰まっている投稿は、cronが動き始めても自動的には修正されません — 一押しが必要です。WP-CLIでこれをきれいに処理できます:
# 詰まっている投稿を確認
wp post list --post_status=future --fields=ID,post_title,post_date
# 特定の投稿を公開(123を実際のIDに置き換える)
wp post update 123 --post_status=publish
まとめて救済する必要がありますか?
wp post list --post_status=future --format=ids | xargs wp post update --post_status=publish
**まず日付を確認してください。**このコマンドは「future」ステータスのすべての投稿を即座に公開します — 来週のために正当にスケジュールされた投稿も含めて。
ステップ5:Cronをブロックしているプラグインを確認する
セキュリティプラグインは頻繁に原因となります。WordfenceとiThemes Securityはどちらもwp-cron.phpへの直接アクセスをブロックするオプションを持っています — ファイアウォールルールや「WP-Cronを無効化」のトグルでその設定を確認してください。
問題を切り分けるには、すべてのプラグインを無効化してテストします:
wp plugin deactivate --all
wp cron event run --due-now
それで動作する場合、プラグインを1つずつ再有効化して問題が再発するまで続けます。最後に有効化したプラグインが原因です。
修正の確認
- 新しい投稿を作成し、2〜3分後にスケジュールする
- その時間が来るまで待つ
- 投稿一覧を更新する — 「公開済み」と表示されているはずです
cronキューを直接確認することもできます:
# 予定されているイベントを一覧表示
wp cron event list
# 次回実行までの時間を確認
wp cron event list --fields=hook,next_run_relative
予防策
- 公開タイミングが重要なサイトでは実際のシステムcronを使用してください — WP-Cronは開発環境には適していますが、本番環境には向いていません
- デバッグ中はWP Crontrolをインストールしてください。スケジュールされたすべてのイベントを読みやすい表形式で表示し、WordPressの管理画面から手動でトリガーできます
- 新しいサーバーやホストに移行した後は、サイトが公開される前にcronが動作していることを確認してください。5分後にスケジュールされたテスト投稿1つで、すぐに確認できます
- 大量のスケジュールタスク(WooCommerceメール、一括エクスポート)にはAction Schedulerが有効です。WP-Cronの上にキュー管理とリトライロジックを追加します

