Cron-задача не запускается: что проверить

Обновлено 3 ноября 2026

Вручную команда работает, строка в crontab выглядит правильно, а в 3 часа ночи ничего не происходит. Cron редко объясняет причину: интерфейса у него нет, а ошибки по умолчанию уходят в локальный почтовый ящик, который никто не читает. Пройдите этот список сверху вниз — первые пункты встречаются чаще всего.

1. Работает ли cron вообще?

systemctl status cron     # Debian, Ubuntu
systemctl status crond    # RHEL, Fedora, Rocky, Alma

В Docker-контейнере демона cron обычно нет, пока вы его сами не запустите; подробнее в руководстве cron-задачи в Docker.

2. Пытался ли cron запустить задачу?

Cron записывает каждый запуск. Если вашей строки в журнале нет, cron её и не запускал; если есть, задача стартовала и упала сама.

journalctl -u cron --since "today"     # или -u crond
grep CRON /var/log/syslog              # Debian, Ubuntu с rsyslog
sudo tail /var/log/cron                # семейство RHEL

3. Окружение почти пустое

Самая частая причина. Cron не читает .bashrc и .profile. Задача получает SHELL=/bin/sh, короткий PATH вроде /usr/bin:/bin и ни одной из ваших переменных. Поэтому node, php, docker или aws из /usr/local/bin или менеджера версий просто не находятся.

Чтобы повторить окружение cron в своей консоли, запустите задачу с пустым окружением:

env -i SHELL=/bin/sh PATH=/usr/bin:/bin HOME="$HOME" /bin/sh -c '/srv/app/job.sh'

4. Знак процента обрезает команду

В crontab % означает перевод строки, и всё после первого такого знака передаётся команде на вход. date +%F молча ломает строку. Экранируйте его как \% или вынесите команду в скрипт:

0 3 * * * /srv/backup.sh > /var/backups/log-$(date +\%F).txt 2>&1

5. Скрипт нельзя выполнить

6. Сам файл crontab

7. Расписание не такое, как кажется

Вставьте выражение в расшифровщик cron-выражений, чтобы увидеть ближайшие запуски словами.

8. Ошибки уходят в никуда

Cron отправляет вывод задачи письмом пользователю или на MAILTO. Без почтового сервера он теряется. На время отладки пишите его в файл:

*/5 * * * * /srv/job.sh >> /var/log/job.log 2>&1

Если ничего не помогло, добавьте временную строку * * * * * env > /tmp/cron-env, подождите минуту и сравните файл с выводом env в своей консоли.

Узнавать в следующий раз без проверок

Всё перечисленное ломается молча. Чтобы не узнавать об этом через несколько недель, пусть задача сообщает о каждом запуске, а вы получаете алерт, если сообщение не пришло. Создайте проверку в Heartcron с тем же расписанием и добавьте пинг в конец строки:

0 3 * * * /srv/backup.sh && curl -fsS -m 10 --retry 5 -o /dev/null https://ping.heartcron.com/<uuid>

Если cron остановится, сервер пересоберут без crontab или скрипт упадёт, пинг не придёт, и вы получите алерт в Telegram, Slack, Discord или на почту. Чтобы видеть ещё и текст ошибки, отправляйте вывод и код завершения:

0 3 * * * /srv/backup.sh 2>&1 | tail -c 100000 | curl -fsS -m 10 --data-binary @- https://ping.heartcron.com/<uuid>/${PIPESTATUS[0]}

Для этой строки нужен SHELL=/bin/bash в начале crontab: PIPESTATUS есть только в Bash. Или установите открытую утилиту heartcron, она сделает то же самое: heartcron run nightly-backup -- /srv/backup.sh.

Другие руководства