Скрипт прекрасно работает, когда вы набираете его имя. Запланированный в crontab, он ничего не делает: ни файла резервной копии, ни письма, ни ошибки. Ситуация «задание cron не выполняется» — одна из самых частых мелких загадок в администрировании Linux, и причина почти никогда не в самом cron. Дело в различии между вашей интерактивной оболочкой и голым окружением, которое cron даёт каждому заданию. Вот обычные причины в том порядке, в котором их стоит проверять, и как создавать задания по расписанию, на которые можно положиться.
1. Задание cron не выполняется? Начните с окружения
Cron запускает задания с минимальным окружением. Он не читает .bashrc и .profile, а PATH в cron по умолчанию — просто /usr/bin:/bin. Команда из /usr/local/bin или /usr/sbin либо инструмент, установленный только для вашего пользователя, попросту не найдены. Переменные окружения cron — тоже короткий список: пароль базы данных, экспортированный в вашем профиле, настройка прокси или языка, на которые вы полагаетесь в интерактивной работе, там отсутствуют.
Исправления: используйте полные пути к командам в скрипте, задайте PATH в начале crontab или скрипта и загружайте любую нужную заданию конфигурацию из файла, который скрипт читает явно. Чтобы увидеть, что именно предоставляет cron, запланируйте разовое задание, которое записывает вывод env в файл в /tmp, и сравните его с вашей оболочкой.
2. Задание выполняется в sh, а не в Bash
Если в crontab не задан SHELL, cron выполняет каждую командную строку в /bin/sh. В Debian и Ubuntu это dash — более простая оболочка, не понимающая возможностей Bash, таких как массивы, проверки в двойных скобках или команда source. Начинайте каждый скрипт со строки #!/bin/bash, делайте его исполняемым и вызывайте из cron скрипт, а не вставляйте в crontab длинные однострочники для Bash.
3. Crontab не работает из-за самого файла
- Знак процента. В командной строке crontab cron превращает неэкранированный знак процента в перевод строки. Классическая жертва — формат даты, переданный прямо в команду date. Экранируйте каждый такой знак обратной косой чертой или перенесите команду в скрипт.
- Последняя строка. После последней записи в crontab нужен перевод строки, иначе запись может быть проигнорирована.
- Поле пользователя. Записи в /etc/crontab и /etc/cron.d содержат имя пользователя между расписанием и командой; личные crontab, редактируемые через crontab -e, — нет. Если перепутать эти два формата, запись не сработает.
- Имена файлов в каталогах cron. В системах на основе Debian скрипты в /etc/cron.daily и подобных папках запускаются run-parts, который пропускает имена файлов с точкой. Скрипт backup.sh, помещённый туда, никогда не запустится; назовите его backup. Файлы в /etc/cron.d подчиняются тому же правилу именования.
- Права доступа. Скрипты в этих папках должны быть исполняемыми, а скрипт, принадлежащий одному пользователю, может быть недоступен для чтения учётной записи, от имени которой запускается задание.
4. Оно выполнилось, но не тогда, когда вы ожидали
Cron следует часовому поясу сервера. Многие облачные серверы работают по UTC, поэтому задание, рассчитанное на 2 часа ночи в Лос-Анджелесе, на самом деле срабатывает ранним вечером по тихоокеанскому времени, а разница сдвигается на час при начале или окончании перехода на летнее время. Проверьте настройку командой timedatectl, а затем либо запишите расписание в поясе сервера, либо намеренно смените пояс. Для заданий, привязанных к рабочим часам, укажите часовой пояс в комментарии рядом с записью.
5. Оно выполнилось и тихо завершилось с ошибкой: где искать журналы cron
По умолчанию cron отправляет вывод задания по электронной почте его владельцу, что никуда не ведёт на серверах без доставки почты. В актуальных Debian и Ubuntu служба cron записывает в журнал systemd каждое запущенное задание, поэтому journalctl -u cron показывает, запускалось ли задание вообще. В Debian 12 и новее rsyslog по умолчанию больше не устанавливается, поэтому /var/log/syslog может отсутствовать, когда вы идёте искать журналы cron. Если задание запустилось, но не дало ничего полезного, перенаправьте его вывод в лог-файл или задайте MAILTO с адресом, который кто-то читает, и пусть скрипт сам сообщает о своих сбоях.
Как сделать задания по расписанию надёжными
Когда задание работает, его работоспособность поддерживает несколько привычек. Они отличают собственные shell-скрипты, о которых можно забыть, от тех, что месяцами тихо не работают, и это правила, на которых строится наша работа по скриптам на Bash и автоматизации:
- Строгий режим. set -euo pipefail заставляет скрипт остановиться на первой неудачной команде, а не продолжать с недостающими данными.
- Без перекрывающихся запусков. Если обернуть задание в flock -n с файлом блокировки, медленный запуск будет пропущен, а не удвоен, когда начнётся следующий.
- Сигнал жизни. По завершении задание сообщает об успехе в проверку мониторинга; если сообщение не пришло, кто-то получает оповещение.
- Таймеры systemd для более тяжёлых заданий. Таймеры systemd пишут в журнал, могут наверстать пропущенные при выключенном сервере запуски с Persistent=true и показывают последний и следующий запуск в systemctl list-timers.
Часто задаваемые вопросы: задание cron не выполняется
Как проверить задание cron, не дожидаясь расписания?
Запустите его в таком же голом окружении: env -i с минимальным PATH, от того же пользователя и через /bin/sh, если cron использует именно его. Если так работает, то из cron тоже будет работать. Также помогает расписание «каждую минуту» на короткое время с наблюдением за журналом.
Почему моё задание cron выполняется дважды?
Обычно потому, что оно запланировано в двух местах, например в личном crontab и в /etc/cron.d, или потому что предыдущий запуск ещё шёл, когда начался следующий. Проверьте crontab -l для каждого пользователя, а также /etc/crontab и /etc/cron.d, и добавьте блокировку через flock.
Почему задание работает из crontab -e, но не из /etc/cron.d?
Почти всегда дело в поле пользователя или в имени файла. Записям в /etc/cron.d нужен столбец с пользователем, а имя файла с точкой игнорируется.
Надоели скрипты, которые работают, только пока на них кто-то смотрит? Наша услуга по индивидуальным скриптам на Bash и автоматизации включает написание, тестирование и документирование заданий по расписанию для резервного копирования, развёртывания и проверок состояния, а наши услуги по скриптам на Bash охватывают и исправление скриптов, написанных кем-то другим. Если вам нужна автоматизация Linux в Лос-Анджелесе и Лонг-Бич, свяжитесь с нами, коротко описав задание и сервер, на котором оно выполняется.




