WP-Cron в WordPress работает не так, как системный cron на сервере. По умолчанию запланированные события проверяются при загрузке страниц, поэтому фактическое время запуска зависит от посещаемости сайта.
На сайте с низкой посещаемостью отправка писем, резервное копирование или очистка кеша могут выполняться с задержкой. На нагруженном ресурсе несколько HTTP-запросов, напротив, могут почти одновременно инициировать одинаковые или тяжелые задачи. Более надежная схема — отключить автоматический запуск WP-Cron во время посещений и запускать очередь через системный cron с помощью WP-CLI.
Почему стандартный WP-Cron может пропускать или откладывать задачи
WordPress сохраняет запланированные события и проверяет их, когда кто-либо открывает страницу. Если на сайте несколько часов нет посетителей, событие может не выполниться в запланированный момент. Оно будет обработано во время следующего подходящего запуска.
Этот механизм также создает дополнительные HTTP-запросы к WordPress. Если одновременно открывается много страниц, несколько процессов могут попытаться запустить планировщик. WordPress защищает от части повторных запусков, но для тяжелых или критически важных задач не стоит полагаться только на эту защиту.
Системный cron работает независимо от трафика. Он запускает WP-CLI по расписанию, а команда проверяет и выполняет события, срок запуска которых уже наступил. Это обеспечивает предсказуемое время выполнения и упрощает поиск ошибок в логах.
- низкая посещаемость не задерживает запланированные события;
- сокращается количество фоновых запусков через обычные HTTP-запросы;
- результат выполнения команд можно централизованно проверять;
- системный cron можно объединить с блокировкой параллельных процессов.
Что подготовить перед настройкой
Для этой схемы нужен доступ к серверу по SSH или другой способ управления системным cron. Также должны быть установлены PHP и WP-CLI, доступные пользователю, от имени которого будет выполняться команда.
Команду следует запускать от имени пользователя веб-сервера или владельца файлов WordPress. Не используйте root без необходимости: это может привести к созданию файлов с неправильным владельцем и увеличить последствия ошибки в команде.
Заранее определите точный путь к сайту, например `/var/www/site`, и проверьте, где находится исполняемый файл WP-CLI. В cron лучше использовать абсолютные пути, поскольку окружение системного cron обычно имеет ограниченный PATH.
- корректный путь к каталогу, в котором находится `wp-config.php`;
- рабочая команда `wp` или ее абсолютный путь, например `/usr/local/bin/wp`;
- права пользователя на файлы WordPress и доступ к базе данных;
- наличие утилиты `flock`, если необходимо запретить параллельные запуски.
cd /var/www/site
wp --info
wp core is-installed
Отключите запуск WP-Cron при загрузке страниц
Откройте `wp-config.php` и добавьте константу до загрузки файла `wp-settings.php`. Обычно ее размещают рядом с другими настройками WordPress, перед строкой, которая сообщает, что дальнейшее содержимое файла изменять не следует.
Эта константа не удаляет запланированные события и не очищает очередь. Она лишь запрещает WordPress инициировать стандартный запуск планировщика во время HTTP-запросов. После этого необходимо обязательно настроить внешний запуск, иначе события перестанут выполняться.
- перед редактированием создайте резервную копию `wp-config.php`;
- убедитесь, что константа не объявлена повторно с другим значением;
- после изменения проверьте, что сайт и WP-CLI корректно подключаются к базе данных.
define('DISABLE_WP_CRON', true);
Добавьте системный cron через WP-CLI
Откройте crontab нужного пользователя командой `crontab -e`. Запуск раз в минуту подходит для большинства сайтов, которым требуется регулярное выполнение событий. Если вашему проекту не нужна такая частота, интервал можно увеличить.
Параметр `--due-now` указывает WP-CLI выполнить события, срок запуска которых уже наступил. Параметр `--path` задает каталог конкретного сайта WordPress, поэтому команда не зависит от текущего рабочего каталога.
Обертка `flock -n` создает неблокирующий lock-файл. Если предыдущий запуск еще выполняется, новый процесс сразу завершится, а не начнет обрабатывать очередь параллельно.
- используйте отдельный lock-файл для каждого сайта;
- проверьте, что пользователь cron может создавать и изменять этот файл;
- при необходимости укажите абсолютный путь к `wp`, а не просто `wp`.
* * * * * flock -n /tmp/site-wp-cron.lock /usr/local/bin/wp cron event run --due-now --path=/var/www/site
Вариант с журналом выполнения
Для диагностики полезно временно или постоянно записывать стандартный вывод команды в файл, к которому имеет доступ пользователь cron. Не указывайте системный путь к логу, если у этого пользователя нет прав на запись.
Перенаправление `2>&1` добавляет сообщения об ошибках в тот же файл. Лог необходимо периодически ограничивать или очищать, чтобы он не заполнил дисковое пространство.
- храните лог в каталоге, доступном пользователю сайта;
- не записывайте в лог конфиденциальные переменные окружения или пароли;
- после завершения диагностики оставьте только необходимый уровень журналирования.
* * * * * flock -n /tmp/site-wp-cron.lock /usr/local/bin/wp cron event run --due-now --path=/var/www/site >> /home/site/logs/wp-cron.log 2>&1
Проверьте очередь событий и первый запуск
После добавления правила не ждите вслепую. Сначала вручную запустите ту же команду от имени пользователя, под которым будет работать cron. Так можно сразу увидеть ошибки доступа, неправильный путь к сайту, проблемы с PHP или подключением к базе данных.
Для просмотра зарегистрированных событий используйте команду списка WP-CLI. Она помогает увидеть название hook, время следующего запуска, периодичность и текущее состояние очереди.
- проверьте, есть ли события, срок запуска которых уже наступил;
- после ручного запуска повторите список и убедитесь, что время следующего выполнения изменилось;
- если обработчик завершается с ошибкой, просмотрите лог ошибок PHP и лог веб-сервера;
- убедитесь, что системный cron действительно загрузил новое правило.
wp cron event list --path=/var/www/site
wp cron event run --due-now --path=/var/www/site
crontab -l
Типичные ошибки при настройке
Самая распространенная ошибка — добавить `DISABLE_WP_CRON`, но не настроить замену. В этом случае очередь накапливается, а фоновые задачи вообще перестают запускаться.
Другая проблема — запускать cron от имени root, когда веб-сервер работает от имени другого пользователя. WP-CLI или плагины могут создать новые файлы с владельцем root, после чего WordPress потеряет возможность изменять их.
Также часто используют относительные пути к `wp`, сайту или лог-файлу. В cron это может не работать из-за другого рабочего окружения. Используйте абсолютные пути и проверяйте команду именно в контексте нужного пользователя.
- не запускайте одновременно старый HTTP-механизм и системный cron, не оценив последствия;
- не удаляйте lock-файл во время активного процесса без предварительной проверки — это может разрешить параллельный запуск;
- не используйте один lock-файл для нескольких независимых сайтов;
- не игнорируйте ошибки WP-CLI, даже если cron формально завершается успешно;
- для multisite при необходимости указывайте правильный сайт с помощью параметра `--url`.
Когда системный cron не решает проблему полностью
Переход на системный cron контролирует момент запуска, но не исправляет ошибки самих обработчиков. Если плагин завершается из-за лимита памяти, заблокированной таблицы, недоступного внешнего API или неправильной логики повторных попыток, проблема сохранится.
Для тяжелых задач важно проверить длительность выполнения, лимиты PHP CLI и поведение при частичном завершении. Некоторые плагины имеют собственные очереди или используют Action Scheduler, поэтому события WP-Cron могут лишь запускать следующий этап обработки.
После настройки установите простую регулярную проверку: просматривайте лог, количество просроченных событий и состояние дискового пространства. Если сервер перезагружался или cron был отключен, очередь может временно накопиться.
- проверяйте лог ошибок PHP после обновления WordPress и плагинов;
- контролируйте, не увеличивается ли количество просроченных событий;
- проверяйте права на lock-файл и каталог логов;
- для критически важных процессов настройте уведомления об ошибках на уровне сервера или системы мониторинга.
Частые вопросы
Нужно ли оставлять WP-Cron включенным после настройки системного cron?
Нет. Если системный cron регулярно запускает `wp cron event run --due-now`, в `wp-config.php` следует оставить `define('DISABLE_WP_CRON', true);`, чтобы WordPress не создавал дополнительные запуски во время посещений.
Почему события все равно выполняются с задержкой?
Проверьте, работает ли cron, правильно ли указаны путь к сайту и пользователь, а также не выполняется ли долго предыдущий процесс. Кроме того, событие может быть зарегистрировано с собственным интервалом или блокироваться ошибкой обработчика.
Обязательно ли запускать WP-Cron каждую минуту?
Нет. Частота зависит от задач сайта. Запуск каждую минуту уменьшает задержку, но для проектов без критически важных событий может быть достаточно интервала в несколько минут.
Что делать, если команда `flock` недоступна?
Проверьте, установлена ли утилита в вашей операционной системе, или используйте другой механизм взаимной блокировки, доступный на сервере. Не убирайте защиту от параллельных запусков для тяжелых задач без оценки рисков.
Вывод
Системный cron вместе с WP-CLI делает запуск WP-Cron предсказуемым: он не зависит от трафика, выполняется от имени определенного пользователя и может быть защищен от параллельных процессов с помощью `flock`.
После настройки важно вручную проверить команду, просматривать очередь через `wp cron event list` и контролировать логи PHP. Это позволяет не только своевременно запускать события, но и быстро находить причины ошибок.