
wp-cron грузит сервер не постоянно, а рывками — и именно поэтому его так долго не находят. Сайт неделю работает нормально, а потом на пять минут превращается в кисель, панель хостинга рисует всплеск нагрузки, и всё снова успокаивается. Причина в том, что планировщик WordPress устроен не так, как планировщик операционной системы: он не живёт своей жизнью по часам, а просыпается на плечах случайного посетителя.
Как на самом деле работает встроенный планировщик
Настоящее расписание в Linux ведёт системная служба: она смотрит на часы и в нужную минуту запускает команду. WordPress так не умеет, потому что не имеет доступа к операционной системе. Вместо этого он делает следующее.
Все запланированные задания хранятся в базе, в таблице настроек, в одной записи с именем cron. Это сериализованный массив: время запуска, имя действия, аргументы, периодичность. При каждом обращении к сайту WordPress заглядывает в этот массив и спрашивает: есть ли задания, время которых уже наступило. Если есть — он отправляет сам себе фоновый запрос на файл wp-cron.php, и уже в этом отдельном процессе задания выполняются.
Отсюда все свойства встроенного планировщика, хорошие и плохие:
- Нет посетителей — нет выполнения. На сайте с двадцатью визитами в сутки отложенная публикация может выйти на три часа позже назначенного времени или не выйти вовсе.
- Много посетителей — много проверок. Каждый заход, включая заходы поисковых роботов и сканеров, — это лишний запрос к базе и потенциальный запуск фонового процесса.
- Нагрузка приходит рывком. Все накопившиеся задания выполняются в один момент, в фоновом процессе, который конкурирует за ресурсы с обычными страницами.
- Первый посетитель платит за всех. Формально фоновый запрос не задерживает страницу, но на дешёвом тарифе с ограничением на число одновременных процессов задержка вполне заметна.
Есть и защитный механизм: пока одно выполнение идёт, ставится блокировка, чтобы задания не запускались параллельно. Держится она порядка минуты. Если процесс упал, не сняв блокировку, следующий запуск будет ждать её истечения — отсюда часть историй про «задания просто перестали выполняться».
Почему нагрузка получается рваной
Представьте типичный сайт с интернет-магазином. На нём висят: проверка обновлений раз в двенадцать часов, отправка накопившихся писем, пересборка карты сайта, предзагрузка кэша, очистка корзин, синхронизация остатков, чистка старых записей журнала, резервное копирование. Часть из них лёгкие, часть тяжёлые.
Ночью посетителей нет. Задания копятся. Утром приходит первый человек — и в этот момент запускаются сразу восемь заданий, среди которых предзагрузка кэша, обходящая двести страниц, и резервное копирование, читающее весь диск. Первые посетители получают сайт, который отвечает секунды вместо десятых долей.
Обратная ситуация не лучше. На посещаемом сайте проверка расписания делается при каждом обращении, а обращений в час может быть несколько тысяч, включая роботов. Даже если ни одно задание не наступило, это тысячи чтений сериализованного массива из базы. Когда этот массив разросся до сотен заданий — а такое бывает, — каждое чтение перестаёт быть бесплатным.
Отдельно про роботов. Сканеры ходят по сайту чаще людей, и каждый их визит тоже дёргает планировщик: чужой сканер разгоняет вашу внутреннюю фоновую работу. Что ещё делает поток автоматических обращений с сервером, разобрано в материале 9 серверных проверок, которые влияют на ранжирование сильнее, чем перелинковка.
Как понять, что тормоза именно отсюда
Прежде чем что-то менять, нужно убедиться, что виноват планировщик, а не медленный сервер, тяжёлая тема или отсутствие кэша. Есть четыре проверки, каждая занимает несколько минут.
Проверка первая: журнал обращений сервера. Откройте лог доступа и найдите строки с wp-cron.php. Смотрите на частоту и время выполнения. Раз в несколько минут при живом трафике — нормально; десятки обращений в минуту означают, что блокировка не работает или задания падают и запускаются заново. Выполнение дольше десяти-пятнадцати секунд — уже проблема.
Проверка вторая: список заданий. Посмотрите, что вообще запланировано. Это делается инструментом просмотра расписания в админке или командой wp cron event list из консоли. Нормальный сайт имеет от десяти до тридцати заданий. Сто с лишним заданий, десятки одинаковых имён подряд, задания с датой запуска в прошлом — всё это признаки беспорядка.
Проверка третья: сопоставление во времени. Возьмите график нагрузки в панели хостинга и сравните пики с временем выполнения тяжёлых заданий. Если всплеск процессорного времени каждый раз совпадает с запуском предзагрузки кэша или резервного копирования, вы нашли виновника без всякой теории.
Проверка четвёртая: размер записи с расписанием. В таблице настроек посмотрите длину значения записи cron. Несколько килобайт — норма. Сотни килобайт означают, что расписание распухло, и каждый визит посетителя тянет из базы этот объём.
Если ни одна проверка ничего не показала, тормоза не отсюда. Куда смотреть в этом случае, я разбирал в материале WordPress тормозит не из-за плагинов: где искать настоящую причину.
Отключаем встроенный запуск и вешаем настоящую задачу
Правильное решение — не «отключить крон», а перенести его запуск с посетителей на систему. Делается это в два шага, и порядок важен: если сделать только первый, задания перестанут выполняться совсем.
Шаг первый. В файле wp-config.php выше строки с комментарием о том, что дальше править не нужно, добавляется константа DISABLE_WP_CRON со значением true. После этого WordPress перестаёт дёргать планировщик при заходах посетителей. Файл wp-cron.php при этом никуда не девается и продолжает работать, если его вызвать напрямую.
Шаг второй. В панели хостинга создаётся системная задача по расписанию. Вариантов вызова два.
- Через консольную утилиту WordPress: команда вида
wp cron event run --due-nowс указанием пути к сайту. Это предпочтительный способ: выполнение идёт напрямую, без веб-сервера, не тратится время на HTTP-запрос, не мешает кэширование, и в журнале видно результат каждой задачи. - Через обращение к файлу: вызов
wp-cron.phpс добавлением параметраdoing_wp_cron. Работает везде, но проходит через веб-сервер со всеми его ограничениями по времени выполнения.
Периодичность: раз в пять минут подходит почти всем, магазину с уведомлениями — раз в минуту, блогу хватит и пятнадцати минут. Помните, что отложенная публикация выйдет с точностью до выбранного интервала.
Отдельно про константу ALTERNATE_WP_CRON, которую советуют в половине статей. Она включает режим, при котором планировщик запускается через перенаправление посетителя с дополнительным параметром в адресе. Он предназначен для серверов, где сайт не может обратиться сам к себе, и даёт побочные эффекты: посторонний параметр в адресах, лишние перенаправления, конфликт с кэшированием. Включайте только если системную задачу создать невозможно.
Зависшие и задвоенные задания
Вторая половина проблемы — не в механизме запуска, а в содержимом расписания.
Задвоение. Плагин при активации создаёт задание. Корректный код сначала проверяет, не создано ли оно уже, и только потом добавляет. Некорректный добавляет всегда. В результате после нескольких включений и выключений плагина в расписании висит пять одинаковых заданий, и каждое честно выполняется. Смотрится это в списке заданий как одинаковые имена подряд.
Зависание. Задание, которое падает с фатальной ошибкой, не переносится на следующий раз корректно и остаётся в расписании с прошедшей датой. При каждом запуске планировщик пытается его выполнить снова, снова получает ошибку — и тратит на это ресурсы бесконечно. В списке такие видны по дате запуска, которая давно прошла.
Наследство от удалённых плагинов. Плагин удалили, а его задания остались в расписании и продолжают вызываться. Действие не найдено, ничего не происходит, но проверка выполняется каждый раз.
Отдельная система очередей. Крупные плагины, и прежде всего магазины, используют собственный планировщик действий, который хранит задачи не в настройках, а в отдельных таблицах базы. Он надёжнее, но таблица разрастается до сотен тысяч строк с завершёнными и неудавшимися действиями, потому что чистка не настроена или не успевает отработать. Проверять её нужно в интерфейсе самого плагина.
Чистка расписания выполняется вручную: посмотреть список, удалить дубликаты, удалить задания несуществующих плагинов, перезапустить зависшие. Полное удаление записи cron тоже работает, но вместе с мусором уйдут задания сторонних плагинов, которые восстановятся только после переактивации.
Какие плагины плодят задачи
Злодеев здесь нет: каждое задание кому-то нужно. Проблема — в количестве и в том, что тяжёлые задания сходятся в одну минуту.
| Тип плагина | Что ставит в расписание | Чем тяжело | Что делать |
|---|---|---|---|
| Кэширование | Предзагрузка кэша, очистка устаревшего | Обход сотен страниц подряд | Ограничить число страниц, разнести по времени |
| Резервное копирование | Архивация файлов и базы | Самая тяжёлая задача на сайте | Только ночью, отдельным системным заданием |
| Магазин | Очередь действий, статусы заказов, остатки | Тысячи мелких задач, распухшие таблицы | Следить за очередью, включить чистку истории |
| SEO-плагины | Пересборка карты сайта, переиндексация внутренних данных | Тяжело на сайтах с десятками тысяч страниц | Увеличить интервал, запускать вручную после массовых правок |
| Статистика и аналитика | Агрегация просмотров, отчёты | Постоянная запись в базу | Отказаться в пользу внешней системы аналитики |
| Антиспам и защита | Проверка файлов, обновление списков | Сканирование всего диска | Реже, в часы минимальной посещаемости |
| Рассылки и уведомления | Отправка писем очередями | Долгое ожидание ответа почтового сервера | Внешний сервис отправки |
| Импорт и синхронизация | Обмен с учётной системой | Длинные запросы к внешним адресам | Отдельное системное задание, не через планировщик WordPress |
Практический вывод из таблицы: тяжёлые задачи — копирование, синхронизацию, предзагрузку кэша — правильнее выносить в отдельные системные задания с собственным временем запуска, а не оставлять внутри общей очереди. Тогда они не сталкиваются друг с другом и не приходятся на утренний приход посетителей. Про то, как связаны серверный кэш и предзагрузка, стоит почитать в материале Что такое серверное кэширование и как его настроить.
Когда встроенный планировщик трогать не надо
Честный раздел: на большинстве небольших сайтов вся эта настройка не нужна, и лезть в неё без причины смысла нет.
Не трогайте, если сайт открывается быстро, нагрузка ровная, отложенные публикации выходят вовремя, а заданий в расписании два десятка. Перенос на системную задачу ничего не улучшит, зато добавит место, где можно ошибиться.
Не начинайте с крона, если сайт тормозит равномерно, а не рывками. Постоянная медлительность — это ответ сервера, отсутствие кэша, тяжёлый шаблон или конструктор страниц. Планировщик даёт именно всплески, а не ровный фон.
И не отключайте встроенный запуск, если у вас нет доступа к созданию системных задач. Константа без второго шага означает, что перестанут выходить отложенные записи, не будут отправляться письма форм, не станут обновляться карта сайта и уведомления поисковым системам. Кстати, механизм мгновенного уведомления об изменениях тоже часто работает через расписание — как он устроен, описано в статье Как установить IndexNow на WordPress.
Наконец, стоит сказать прямо: тема эта почти не имеет спроса в поиске. Её не ищут, пока не столкнутся. Поэтому текст написан для тех, кто уже увидел рваную нагрузку в панели или получил от хостинга письмо о превышении лимитов, — и ему нужен порядок действий, а не рассуждения о пользе автоматизации.
Чеклист настройки
Порядок, в котором имеет смысл двигаться, если признаки совпали.
| Шаг | Действие | Результат, который надо увидеть |
|---|---|---|
| 1 | Найти обращения к wp-cron.php в логе доступа | Понятна частота и длительность запусков |
| 2 | Посмотреть полный список запланированных заданий | Видны дубликаты, зависшие и чужие задания |
| 3 | Удалить дубликаты и задания удалённых плагинов | Список сократился до реально нужного |
| 4 | Проверить очередь действий магазина | Таблица очереди не растёт бесконечно |
| 5 | Добавить DISABLE_WP_CRON в wp-config.php | Запуски от посетителей прекратились |
| 6 | Создать системное задание раз в 1–5 минут | Задания выполняются по расписанию |
| 7 | Проверить отложенную публикацию тестовой записью | Запись вышла в назначенное время |
| 8 | Вынести копирование и синхронизацию отдельными заданиями | Тяжёлые задачи не пересекаются |
| 9 | Сравнить график нагрузки через сутки | Пики стали ниже и предсказуемее |
| 10 | Проверить отправку формы и письма | Письма приходят, очередь не копится |
Седьмой и десятый пункты пропускают чаще всего, а именно они ловят самую дорогую ошибку — константу без системного задания. Признак такой поломки очень характерный: в списке записей появляется отметка о пропущенном расписании публикации, а письма от форм перестают доходить, хотя форма отправляется без ошибок. Замедление сайта при этом действительно уходит: он же ничего больше не делает.
Частые вопросы
Можно ли просто удалить файл wp-cron.php? Нет. Удаление файла не отключает механизм, а ломает его: WordPress продолжит отправлять запрос, будет получать ошибку 404 и тратить на это ресурсы. Плюс файл вернётся при следующем обновлении ядра. Отключение делается константой, а не удалением.
Хостинг не даёт создавать задачи по расписанию. Что делать? Есть три пути. Первый — внешний сервис, который по расписанию обращается к адресу вашего wp-cron.php; работает, но зависит от чужой площадки. Второй — оставить встроенный механизм и вместо его отключения разобраться с содержимым расписания: убрать дубликаты, вынести тяжёлые задачи, увеличить интервалы. Часто этого достаточно. Третий — сменить тариф или площадку: отсутствие системных задач обычно означает и другие ограничения.
Как понять, что моя новая системная задача действительно работает? Самая простая проверка: запланируйте публикацию тестовой записи через десять минут и посмотрите, вышла ли она вовремя. Дополнительно можно посмотреть в списке заданий время следующего запуска — оно должно двигаться вперёд без вашего участия.
Насколько сильно это ускоряет сайт? Честный ответ: постоянную скорость страниц почти не меняет. Меняет предсказуемость — исчезают случайные провалы, когда одному посетителю из ста страница отдаётся в несколько раз дольше. На сайтах с жёстким лимитом процессов у хостинга эффект бывает заметнее, потому что фоновые процессы перестают конкурировать с посетителями. Как медленный и нестабильный ответ отражается на выдаче, разобрано в материале Медленный сайт = низкие позиции: как скорость загрузки влияет на ранжирование в Яндексе.
Коротко
- Встроенный планировщик WordPress запускается не по часам, а при заходе посетителя, — отсюда рваная нагрузка и пропущенные публикации на малопосещаемых сайтах.
- Диагностика начинается с лога обращений к
wp-cron.php, списка запланированных заданий и сопоставления пиков нагрузки с временем запусков. - Правильная схема — константа
DISABLE_WP_CRONплюс системная задача раз в 1–5 минут; без второго шага сайт перестанет публиковать и отправлять письма. - Отдельная беда — задвоенные задания, зависшие с прошедшей датой и наследство удалённых плагинов; их нужно чистить руками.
- Тяжёлые задачи вроде резервного копирования и синхронизации выносятся в собственные системные задания с отдельным временем.
- Если сайт тормозит ровно, а не всплесками, причина не здесь — смотрите ответ сервера, кэш и шаблон.
Планировщик — одна из тех вещей, которые не приносят трафика напрямую, но регулярно портят впечатление о сайте: то отложенная статья не вышла, то страница открывалась четыре секунды у случайного посетителя. Проверить, откуда на конкретном сайте берутся всплески нагрузки, можно через бесплатный технический аудит сайта, а разобрать результат вместе и решить, что править первым, — на SEO-консультации по вашему сайту. Если же техническая часть уже в порядке и нужен рост в выдаче, посмотрите, как устроены услуги SEO-продвижения.
Увеличьте позиции и продажи вашего сайта
Профессиональное SEO-продвижение с гарантией результата. Выберите подходящую услугу:
Остались вопросы по продвижению?
Меня зовут Анатолий Кузнецов, я SEO-оптимизатор с 20-летним стажем. Разберу ваш сайт, отвечу на вопросы и подскажу, что улучшить для роста позиций в Яндексе и Google.
Связаться со мной →
Комментарии
Лукерья Вельяминова
Прописала константу в wp-config, а системную задачу создать забыла. Через неделю обнаружила, что ни одна отложенная статья не вышла и письма с форм не приходят. Как теперь разгрести очередь?
Анатолий Кузнецов автор
Разгребается это довольно спокойно. Сначала создайте системную задачу, как описано, с интервалом раз в пять минут. После первого же запуска накопившиеся задания начнут выполняться, но не все сразу: очередь разберётся за несколько циклов, потому что на каждый запуск действует ограничение по времени. Дальше отдельно разберитесь с записями: те, что получили отметку о пропущенном расписании, автоматически не выйдут — их надо открыть и опубликовать вручную либо назначить новую дату. С письмами хуже: сообщения формы, которые не ушли, чаще всего нигде не сохраняются, поэтому проверьте, есть ли в плагине формы журнал отправок, и если он включён, обращения оттуда можно достать. На будущее — после любой правки wp-config проверяйте публикацию тестовой записи, это две минуты.
Христофор Задорожин
Посмотрел список заданий — 214 штук. Из них штук сорок с одинаковым именем от плагина, который я удалил ещё весной. Это нормально вообще?
Анатолий Кузнецов автор
Ненормально, но встречается постоянно. Сорок одинаковых заданий — это плагин, который при каждой активации добавлял задание без проверки, есть ли оно уже. А то, что они остались после удаления плагина, — обычное дело: при удалении чистят за собой немногие. Порядок действий такой. Сначала снимите копию базы, это одна кнопка. Потом удалите все задания, чьё действие принадлежит несуществующим плагинам, — в интерфейсе просмотра расписания такие обычно помечены как не имеющие обработчика. Затем оставьте по одному экземпляру дублирующихся заданий действующих плагинов. После чистки посмотрите на размер записи cron в настройках: если он был сотни килобайт, вы заодно ускорите каждый визит посетителя, потому что этот массив читается из базы постоянно.
Таисия Ефимовская
У нас магазин, таблица очереди действий разрослась до 900 тысяч строк. База стала весить больше двух гигабайт. Чистить можно прямо запросом?
Анатолий Кузнецов автор
Запросом можно, но осторожно и точно не одним. Во-первых, копия базы обязательна. Во-вторых, удалять нужно только записи в статусе завершённых и отменённых, оставив запланированные и выполняющиеся, иначе сломаете текущие процессы магазина. В-третьих, удалять партиями по несколько тысяч строк с паузой: попытка снести девятьсот тысяч одним запросом почти наверняка приведёт к блокировке таблицы и падению сайта. Не забудьте про связанную таблицу с журналом действий — она обычно ещё больше. И после чистки зайдите в настройки магазина и включите ограничение срока хранения истории действий, иначе через полгода вернётесь к тому же объёму. Отдельно проверьте, почему очередь так разрослась: часто причина в том, что задания падают с ошибкой, повторяются и накапливаются.
Руфина Щербатова
Хостинг разрешает системные задачи не чаще раза в 15 минут. Для блога это нормально или лучше оставить как есть?
Анатолий Кузнецов автор
Для блога пятнадцать минут — вполне рабочий интервал, и он лучше встроенного механизма, потому что запуск перестаёт зависеть от того, зашёл кто-то на сайт или нет. Единственное, к чему надо привыкнуть: отложенная публикация выйдет с точностью до пятнадцати минут, поэтому не назначайте время впритык к рассылке или анонсу. Если на сайте есть формы с уведомлениями, проверьте, отправляет ли плагин письмо сразу или ставит его в очередь: во втором случае клиент получит ответ с задержкой, и тут интервал уже имеет значение. Ещё вариант — комбинация: системная задача раз в пятнадцать минут для обычной работы плюс отдельное задание на резервное копирование ночью, чтобы оно не попадало в общую очередь.
Авдей Кожевин
Всплески нагрузки у нас каждое утро в районе восьми. Совпадает с предзагрузкой кэша, теперь понятно. Ограничил число страниц — стало ровнее.
Иннокентий Яхонтов
Про ALTERNATE_WP_CRON полезно. У нас его когда-то включил подрядчик, и в адресах болтался лишний параметр, из-за которого кэш вообще не срабатывал.
Мефодий Нежданов
Запись cron в настройках весит 480 килобайт. Даже не подозревал, что такое бывает. Иду смотреть, что там накопилось.
Демид Шабанов
Хороший раздел про то, когда трогать не надо. У меня сайт на 50 визитов в день, полез настраивать — а проблемы-то и не было.
Эмилия Ильинская
Вопрос: если запускать через консольную утилиту, а не через обращение к файлу, задания точно те же выполняются?
Анатолий Кузнецов автор
Те же самые: расписание одно, хранится оно в базе, а способ запуска только определяет, кто именно его прочитает. Разница в окружении. При обращении к файлу задания выполняются через веб-сервер, значит, действуют его ограничения по времени выполнения и по памяти, а результат вы нигде не увидите. При запуске консольной утилитой ограничения обычно мягче, вывод пишется в журнал задачи, и там сразу видно, какое задание отработало, а какое упало с ошибкой. Есть один нюанс: некоторые плагины ведут себя по-разному в зависимости от того, определён ли адрес сайта, поэтому в команде обязательно указывайте путь к каталогу сайта, а при нескольких доменах — ещё и адрес. После настройки прогоните команду руками один раз и посмотрите вывод: если там ошибки прав доступа, задача из панели тоже работать не будет.
Глафира Трубецкая
Получила от хостинга письмо о превышении лимита процессов. Пошла смотреть логи — там wp-cron.php по сорок раз в минуту. Похоже, блокировка не отрабатывает.
Августа Голицына
Тестовая запись — отличная проверка. Простая, а я бы не догадалась, что можно так убедиться в работе расписания.
Митрофан Рогожин
Вынес резервное копирование в отдельное ночное задание, как советуете. Утренние тормоза пропали полностью.