OpsPulse

Почему cron не запускается: 7 причин и как их проверить

03.10.2026 3 мин чтения cronlinuxdebug

Классическая ситуация: команда работает в терминале, вы добавляете её в crontab — и ничего не происходит. Логов нет, ошибок нет, просто тишина.

Ниже причины по убыванию частоты, с командами для проверки.

1. Урезанный PATH

Самая частая причина. Cron запускает задачи с минимальным окружением: обычно это только /usr/bin:/bin. Ваш .bashrc не подключается, а nvm, pyenv и rbenv недоступны.

Посмотреть, что видит cron:

* * * * * env > /tmp/cron-env.txt

Подождите минуту и сравните файл с выводом env в терминале.

Решение — указывать абсолютные пути:

0 3 * * * /usr/local/bin/python3 /opt/app/task.py

Либо задать PATH в начале crontab:

PATH=/usr/local/bin:/usr/bin:/bin

2. Нет перевода строки в конце файла

Ошибка, которую сложно заметить. Если последняя строка crontab не заканчивается символом новой строки, cron молча её игнорирует.

crontab -l | tail -c 1 | xxd

Должно вывести 0a. Если нет — откройте crontab -e, поставьте курсор в конец последней строки и нажмите Enter.

3. Символ % не экранирован

В crontab % — специальный символ: он превращается в перевод строки, а всё после первого % уходит команде на stdin.

# не сработает
0 3 * * * tar -czf /backup/site-$(date +%Y%m%d).tar.gz /var/www

# правильно
0 3 * * * tar -czf /backup/site-$(date +\%Y\%m\%d).tar.gz /var/www

4. Задача запускается, но падает

Cron отправляет вывод на локальную почту, которую обычно никто не читает. Перенаправьте вывод в файл:

0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1

Ключевое здесь — 2>&1. Без него в лог попадёт только stdout, а ошибки исчезнут.

5. Сервис cron не запущен

systemctl status cron     # Debian, Ubuntu
systemctl status crond    # RHEL, CentOS, Rocky

Отдельно проверьте, что задача вообще попала в планировщик:

grep CRON /var/log/syslog | tail -20

На системах без syslog поможет journalctl -u cron --since today.

6. Права на файл и shebang

ls -l /opt/backup.sh

У файла должен быть бит исполнения (x). Если его нет:

chmod +x /opt/backup.sh

И первая строка скрипта должна указывать интерпретатор:

#!/usr/bin/env bash

7. Предыдущий запуск ещё не завершился

Если прошлый запуск завис, следующий может конфликтовать с ним за ресурсы или лок-файл. Защититься помогает flock:

0 * * * * /usr/bin/flock -n /tmp/task.lock /opt/task.sh

Флаг -n означает: если лок занят, новый запуск сразу завершается, а не встаёт в очередь.

Главная проблема остаётся

Все семь пунктов объединяет одно: о сбое вы узнаёте постфактум. Скрипт молчал неделю, и обнаружилось это случайно — когда понадобился бэкап.

Классический мониторинг здесь не помогает: сервер отвечает, диск на месте, процессы работают. Просто задача не выполнилась.

Решение — обратная логика. Скрипт сам сообщает об успешном завершении, а если сообщение не пришло вовремя, приходит алерт:

0 3 * * * /opt/backup.sh && curl -fsS -m 10 --retry 3 https://opspulse.ru/ping/<uuid>

Оператор && гарантирует, что пинг уйдёт только при успешном завершении. Не отработала задача — через заданный допуск приходит уведомление в Telegram или на почту.

Если задача запускается не через равные промежутки, а, например, по понедельникам и четвергам, в OpsPulse можно указать то же cron-выражение, что и в вашем crontab. Тогда пинг будет.

OpsPulse

Проверьте, что ваши задачи реально работают

Одна строка в crontab — и вы узнаете о сбое раньше клиента. Бесплатный тариф навсегда.

Начать бесплатно