WordPressの予約投稿が「予約済み」のまま公開されない問題を修正する(wp-cron無効時)

intermediate📝 WordPress2026-03-26| WordPress 5.x/6.x、PHP 7.4以降、Linux/cPanel/Nginx/Apache、共有ホスティングまたはVPS

Error Message

Scheduled posts remain in 'Scheduled' status and are never published automatically
#wordpress#wp-cron#予約投稿#cronジョブ#公開

問題の概要

午前9時に投稿をスケジュールしました。9時になっても、投稿は「スケジュール済み」のステータスのまま — 通知もなく、エラーもなく、ただ沈黙。管理画面を更新しても変わりません。投稿が詰まっています。

このような状況では、ほぼ毎回原因は同じです:wp-cronです。

根本原因

WordPressは実際のシステムcronを使用していません。代わりに、WP-Cronwp-cron.php)という独自の疑似スケジューラを持っており、投稿の公開、メール送信、プラグインのジョブ、その他の時間ベースのタスクを処理します。問題は?誰かがサイトを訪問したときにしか実行されないという点です。訪問者がいなければ、cronも動きません。

この設計はアクセスの多いサイトでは問題なく機能します。しかし、以下のような状況では破綻します:

  • DISABLE_WP_CRONwp-config.phptrueに設定されている — マネージドホストや「パフォーマンス最適化」ガイドに従った後に非常によく見られます
  • アクセスの少ないサイト — 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_CRONtrueに設定し、システム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の上にキュー管理とリトライロジックを追加します

Related Error Notes