Задача в crontab есть, а результата нет. Ниже причины, сгруппированные по тому, что именно не работает. Сначала выясните, запускал ли cron задачу вообще. Для этого посмотрите журнал:
journalctl -u cron --since today | grep backup.sh # в CentOS и AlmaLinux: -u crond
Если строки CMD (…) с Вашей задачей нет, cron её не запускал, начните с первых разделов. Если строка
есть, задача запустилась и упала, переходите к разделам ниже. Подробная пошаговая проверка — в руководстве
«Как проверить, что cron выполняется».
Почему cron вообще не запускает задачи?
- Сервис остановлен.
systemctl status cronдолжен показыватьactive (running). Запустить и включить автозапуск:sudo systemctl enable --now cron. - Задача в контейнере. В Docker-контейнере cron обычно не запущен, даже если установлен.
- Пользователю запрещён cron. Если на сервере есть файл
/etc/cron.allow, cron работает только для перечисленных в нём пользователей. Если есть/etc/cron.deny, пользователи из него cron использовать не могут.
Почему cron не видит задачу?
- Задача у другого пользователя.
crontab -lпоказывает только Ваш crontab. Задачиdeployсмотрите черезsudo crontab -u deploy -l. - Нет перевода строки в конце. Последняя строка crontab без перевода строки после неё во многих версиях cron пропускается. Добавьте пустую строку в конец файла.
- Файл в
/etc/cron.d/игнорируется. В Debian и Ubuntu cron пропускает файлы, в имени которых есть точка, напримерbackup.cron. Ещё файл должен принадлежатьrootи быть недоступен для записи другим пользователям. И в этих файлах между расписанием и командой нужно имя пользователя:0 3 * * * deploy /home/deploy/backup.sh. - Скрипт в
/etc/cron.daily/не запускается. Скрипты из этих папок запускаетrun-parts, а в Debian и Ubuntu он пропускает файлы с точкой в имени.backup.shзапущен не будет, переименуйте его вbackup. Проверить, что попадёт в запуск:run-parts --test /etc/cron.daily.
Почему задача запускается не в то время?
- Ошибка в расписании.
* 3 * * *значит «каждую минуту с 03:00 до 03:59», а не «в 03:00». Разобрать выражение можно в руководстве о расписании cron. - День месяца и день недели вместе.
0 3 1 * 1срабатывает первого числа или в понедельник. - Часовой пояс. Cron работает в часовом поясе сервера, а он часто UTC. Проверьте командой
date. Если часовой пояс меняли, перезапустите cron:sudo systemctl restart cron. - Сервер был выключен. Cron не выполняет пропущенные запуски. Если в 03:00 сервер перезагружался, задача не выполнится до следующего раза.
Почему задача запускается, но падает?
Сначала сохраните вывод задачи, иначе причину не узнать:
0 3 * * * /home/deploy/backup.sh >> /var/log/backup.log 2>&1
Дальше смотрите на текст ошибки в логе.
command not found. У cron короткийPATH, обычно только/usr/bin:/bin. Пишите полные пути к программам (/usr/bin/php,/usr/local/bin/node) или задайтеPATHв начале crontab.Permission denied. У скрипта нет права на запуск:chmod +x /home/deploy/backup.sh. Или задача работает от пользователя, которому не хватает прав на файлы./bin/bash^M: bad interpreter. Скрипт сохранён с переводами строк Windows. Исправить:sed -i 's/\r$//' backup.sh.No such file or directoryдля файлов, которые точно есть. Скрипт открывает файлы по относительному пути, а cron запускает его из домашней папки. Добавьтеcdв нужную папку или используйте абсолютные пути.- Команда обрезана. Символ
%в crontab означает перевод строки.date +%Fнужно писать какdate +\%F. - Не хватает переменных окружения. Cron не читает
.bashrcи.profile. Переменные, которые есть в терминале, в cron пустые. Задайте их в начале crontab или в самом скрипте. - Синтаксис bash не работает. Cron запускает команду через
/bin/sh. Если в строке crontab есть конструкции bash, вынесите команду в скрипт с#!/bin/bashв первой строке.
Быстро проверить, упадёт ли команда в окружении cron, можно без ожидания:
env -i HOME="$HOME" SHELL=/bin/sh PATH=/usr/bin:/bin /bin/sh -c '/home/deploy/backup.sh'
Почему задача иногда не выполняется?
- Задачи наслаиваются. Если задача иногда идёт дольше интервала, следующий запуск начнётся поверх
предыдущего, и они мешают друг другу. Запретить наслоение можно через
flock:/usr/bin/flock -n /tmp/import.lock /home/deploy/import.sh. - Предыдущий запуск завис. С
flockзависшая задача держит блокировку, и новые запуски молча пропускаются. Ограничьте время работы:timeout 30m /home/deploy/import.sh. - Внешние сервисы. Задача ждёт ответа от API или базы, и иногда не дожидается. Это видно только в её собственном логе.
Как узнавать о таких сбоях сразу?
Все причины выше объединяет одно: cron о них не сообщает. Задача просто перестаёт делать свою работу, и это обнаруживают, когда что-то уже сломалось.
Чтобы узнавать сразу, задача должна сама сообщать, что отработала, а кто-то должен ждать этого сообщения. Так работает Steadrun. В конец строки crontab добавляется запрос на адрес проверки, и если он не пришёл вовремя, приходит алерт в Telegram или на почту.
0 3 * * * /home/deploy/backup.sh && curl -fsS -m 10 --retry 3 -o /dev/null https://steadrun.ru/ping/ВАШ-UUID
Так ловится любая причина из списка, будь то остановленный cron, ошибка в расписании или упавший скрипт. Как подключить за пять минут, описано в быстром старте. Бесплатно можно следить за пятью задачами.