WP-cron по расписанию
WP-cron по расписанию: зачем переводить и как настроить
Хостинг прислал диагностику одного из моих сайтов: «Основная причина всплеска нагрузки — множество запросов от ботов без реферера» и, что не менее важно, «на сайте неоптимизирован CRON» — с логом, где POST /wp-cron.php?doing_wp_cron=… шел каждые 5 секунд, и каждый запуск занимал 0,2–0,6 секунды. Разбираю, почему так происходит, чем это плохо и как исправить за десять минут.
Что такое WP-cron и почему он «неоптимизированный»
WP-cron — встроенный в CMS планировщик задач: отложенные публикации, письма, бэкапы, проверка обновлений. Механика «из коробки»: при каждом обращении к любой странице сайта WordPress проверяет, есть ли просроченные задачи, и если есть — запускает wp-cron.php.
Проблемы этой механики:
- Задачи выполняются не вовремя. Задание «выполнить в 10:30» выполнится, когда на сайт придёт первый посетитель. Нет посетителей — не выполнится никто.
- Всплески нагрузки в случайные моменты. Каждый посетитель может породить запуск планировщика: на живом сайте это десятки параллельных
wp-cron.phpв минуту, каждый — отдельный PHP-процесс с полной загрузкой WordPress. - Конфликт с кэшированием. Как только сайт начинает отдавать страницы из кэша, обращения к PHP исчезают — и планировщик перестаёт срабатывать вовсе. Отложенный пост может «зависнуть» на часы.
Хостинг видит это как всплески потребления ресурсов и присылает предупреждения — как на скриншоте выше.
Что делать: три шага
Шаг 1. Отключить запуск «по посетителям»
В wp-config.php (до строки $table_prefix) добавить:
define( 'DISABLE_WP_CRON', true );
Проверить, что страницы открываются как раньше (эта константа отключает только автоматический запуск планировщика, сайт работает штатно).
Шаг 2. Запускать планировщик по расписанию
Два варианта — зависит от типа хостинга.
Шаред-хостинг с панелью (планировщик в панели): задание с запуском wp-cron.php через wget/curl:
*/15 * * * * wget -q -O /dev/null https://домен.рф/wp-cron.php
Частота — раз в 15–60 минут: для блогов хватает часа, для сайтов с отложенными публикациями — 15 минут. Если сайтов несколько, разнесите минуты (0, 15, 30 / 5, 20, 35…), чтобы они не стартовали одновременно.
Свой VPS с wp-cli (мой случай — CloudPanel, nginx): запускать через wp-cli только просроченные задачи — это точнее и легче, чем дёргать весь wp-cron.php. В /etc/cron.d/ отдельный файл на каждый сайт, запуск от пользователя сайта:
0,15,30,45 * * * * site1 /usr/bin/wp cron event run --due-now --quiet --path=/home/site1/htdocs/site1.ru
5,20,35,50 * * * * site2 /usr/bin/wp cron event run --due-now --quiet --path=/home/site2/htdocs/site2.ru
Нюансы: минуты у сайтов разнесены; запуск строго от пользователя сайта (не от root — файлы, созданные задачами, будут принадлежать root); --due-now выполняет только те задачи, что действительно пора.
Шаг 3. Проверить
- Разово выполнить
wp cron event run --due-nowвручную — команда должна отработать без ошибок. - Через полчаса посмотреть
wp cron event list: просроченных задач быть не должно. - Удобно смотреть планировщик изнутри: плагин WP Crontrol показывает все задачи, интервалы и время следующего запуска.
Почему это стоит делать
- Ровная нагрузка вместо случайных всплесков: хостинг перестаёт присылать предупреждения, соседи по шареду не страдают.
- Задачи выполняются вовремя: отложенные публикации выходят минута в минуту, письма и бэкапы не задерживаются на часы.
- Совместимость с кэшированием: после перевода на расписание можно без опасений включать агрессивный кэш страниц — планировщику всё равно, приходят ли посетители.
- Это рекомендуемая самим WordPress настройка для нагруженных и кэшируемых сайтов, а не экзотика.
Бонус: что ещё показала та диагностика
Вторая причина всплеска на том же сайте — бот-трафик без referer (Intactus, Baiduspider, Reflectionbot и подобные): десятки запросов к поиск по сайту и fulltext-профилям. Хостинг в той же диагностике даёт готовое правило для .htaccess с фильтрацией по QUERY_STRING, HTTP_REFERER и HTTP_USER_AGENT — такие запросы стоит отрезать на уровне сервера, до загрузки WordPress. Это отдельная тема, но проверьте свои логи: боты-«пылесосы» дают сопоставимую с кроном нагрузку.
Замечание про несколько сайтов
Если сайтов несколько, у каждого свой wp-config.php и своя строка в кроне — константа ставится индивидуально. И не забудьте: после DISABLE_WP_CRON отложенная публикация сработает в ближайший запуск крона (± интервал), а не в секунду наступления времени — выбирайте интервал под свои задачи.
