Спасибо!

Мы Вам перезвоним.

Как настроить cron в Ubuntu

16 2026
12:24PM

Cron запускает команды по расписанию. Свое расписание правят командой crontab -e: одна строка равна одному заданию, в ней пять полей времени и сама команда. Описание ниже опирается на справку crontab(5) из документации Ubuntu и подходит для 22.04, 24.04 и 26.04.

Большинство «не работающих» заданий ломается в трех местах. Cron запускает команду в урезанном окружении, не читает ваш профиль. Он по-своему обращается с символом % и с комментариями в строке. А вывод задания никуда не попадает, если на сервере нет почты. Дальше по порядку: где лежат задания, как записать расписание, на чем спотыкаются и как найти причину, когда задание молчит.

Где cron хранит задания

У каждого пользователя свой crontab. Его открывают командой crontab -e, а сам файл лежит в /var/spool/cron/crontabs/. Руками туда лучше не лазить: через команду crontab файл попадает на место правильным путем, и она заодно проверяет синтаксис.

Системные задания записывают в /etc/crontab и в файлы каталога /etc/cron.d/. Формат почти тот же, только между временем и командой стоит имя пользователя, от которого запустится задание. В личном crontab этого поля нет, и это первая вещь, на которой путаются, когда копируют строку из системного файла в личный.

Есть и третий вариант: положить скрипт в /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly или /etc/cron.monthly. Время запуска для них задает система, указывать расписание не нужно.

Куда писать Поле пользователя Когда подходит
crontab -e нет Задание одного пользователя
/etc/crontab, /etc/cron.d/ да Системное задание или задание от имени другого пользователя
/etc/cron.daily и соседние каталоги не используется Скрипт, которому хватает «раз в час, день, неделю или месяц»

Как устроена строка расписания

Строка состоит из пяти полей времени, разделенных пробелами, и команды:

30 3 * * * /opt/scripts/backup.sh

Здесь скрипт запустится каждый день в 3:30. Поля идут в таком порядке:

Поле Допустимые значения
Минута 0-59
Час 0-23
День месяца 1-31
Месяц 1-12
День недели 0-7, где 0 и 7 обозначают воскресенье

Внутри полей работают четыре символа: * значит «любое значение», запятая перечисляет (1,15), дефис задает диапазон (9-18), косая черта задает шаг (*/10 означает каждые десять минут). Месяцы и дни недели можно писать тремя первыми буквами, например mon или jan, но только по одному: в диапазонах и списках имена справка не разрешает. Поэтому «с понедельника по пятницу» пишут как 1-5, а не mon-fri.

Вместо пяти полей бывают сокращения. @reboot запускает команду один раз при старте системы, @daily раз в сутки.

Где спотыкаются в синтаксисе

Комментарий в строке с командой. Справка прямо говорит: комментарий нельзя ставить в одну строку с командой или с переменной окружения, он станет частью команды. Для переменной это ломает значение: после PATH=/usr/bin # свой путь в PATH окажется и хвост. В строке с командой комментарий оболочка обычно проглотит, но если в нем встретится процент, cron оборвет команду раньше времени. Пишите комментарии отдельной строкой, которая начинается с #.

Символ процента. Cron считает первый неэкранированный % концом команды, а все, что после него, подает команде на стандартный ввод. Поэтому date +%F в crontab не работает, нужно date +\%F.

День месяца и день недели. Если заполнены оба поля, команда срабатывает при совпадении любого из них, а не обоих сразу. Строка 30 4 1,15 * 5 запустится в 4:30 первого и пятнадцатого числа и еще в каждую пятницу. Если нужно «только по пятницам, которые выпали на 1 или 15», условие придется проверять внутри самой команды.

Смена времени. Задания, попавшие в пропущенный при переводе часов интервал, сработают вскоре после него. Задания в повторяющемся часе выполнятся один раз, если только они и так не идут каждую минуту или каждый час. Если в часовом поясе сервера часы не переводят, этот пункт можно пропустить.

Как создать задание и проверить, что оно работает

Начните с проверки службы:

systemctl status cron

Если такой службы нет, cron не установлен. На минимальных образах Ubuntu так бывает, ставится он командой sudo apt install cron.

Дальше откройте свой crontab командой crontab -e. При первом запуске система предложит выбрать редактор. Допишите строку с заданием, сохраните файл. Перезапускать cron после правки не нужно, он подхватывает изменения сам. Список своих заданий показывает crontab -l, а чужой crontab открывают от root: sudo crontab -u deploy -e.

Прежде чем ставить настоящее расписание, прогоните тестовое. Добавьте строку, которая каждую минуту дописывает дату в файл:

* * * * * date >> /tmp/cron-test.log 2>&1

Подождите пару минут, прочитайте /tmp/cron-test.log и сразу удалите тестовую строку. Если записи появились, сам cron работает, а дальше вопрос только в вашей команде.

Пять примеров расписания

Строка Когда сработает На что смотреть
30 3 * * * /opt/scripts/backup.sh Каждый день в 3:30 Скрипт должен быть исполняемым (chmod +x), путь полный
*/15 * * * * /opt/scripts/check.sh Каждые 15 минут, в 0, 15, 30 и 45 минут часа Шаг считается от начала часа
0 9 * * 1-5 /opt/scripts/report.sh В 9:00 с понедельника по пятницу Диапазон цифрами, не mon-fri
30 4 1,15 * 5 /opt/scripts/clean.sh В 4:30 первого и пятнадцатого числа и по пятницам Дни месяца и недели работают как «или»
0 2 * * * tar -czf /backups/www-$(date +\%F).tar.gz /var/www Каждый день в 2:00, архив с датой в имени Процент экранирован

Окружение: что cron задает сам

Команда, которая спокойно работает в терминале, из cron часто падает. Причина почти всегда в окружении: cron не читает ~/.bashrc и профиль, а выдает заданию минимальный набор.

Переменная Значение по умолчанию
SHELL /bin/sh
LOGNAME, HOME Из записи владельца crontab в /etc/passwd
PATH /usr/bin:/bin

Отсюда два следствия. Первое: программы из /usr/local/bin, /sbin или из окружений вроде pyenv и nvm cron не найдет. Пишите полные пути, а если команд много, задайте PATH в начале crontab. Переменные действуют только на строки, которые стоят ниже них.

PATH=/usr/local/bin:/usr/bin:/bin
30 3 * * * backup.sh

Второе: на Ubuntu /bin/sh это dash, и конструкции вроде [[ ... ]] в строке crontab не сработают. Либо переписывайте их под обычный sh, либо добавьте в начало файла SHELL=/bin/bash.

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

env -i SHELL=/bin/sh HOME="$HOME" LOGNAME="$USER" PATH=/usr/bin:/bin /bin/sh -c '/opt/scripts/backup.sh'

Если скрипт падает здесь, а в обычном терминале нет, причина в окружении.

Куда уходит вывод и где искать логи

Все, что задание напечатало, cron отправляет письмом владельцу crontab. Адресата меняет переменная MAILTO, а MAILTO="" письма отключает. Подвох в том, что без почтовой системы на сервере письмо уйти не может: в журнале появляется запись No MTA installed, discarding output, и вывод пропадает вместе с текстом ошибки.

Поэтому вывод перенаправляют в файл сами:

*/10 * * * * /opt/scripts/sync.sh >> /var/log/sync.log 2>&1

Порядок важен: сначала >> в файл, потом 2>&1, чтобы ошибки шли туда же. Пользователь, от имени которого работает задание, должен иметь право писать в этот каталог.

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

journalctl -u cron.service --since today
grep CRON /var/log/syslog

В записи будет примерно такая строка: CRON[12345]: (root) CMD (/opt/scripts/backup.sh). Она говорит только о том, что cron запустил команду. Получилось ли у команды что-то сделать, видно лишь в вашем собственном логе.

Файла /var/log/cron, как в CentOS, в Ubuntu нет. Бывает и так, что нет /var/log/syslog: на минимальных образах не установлен пакет rsyslog. Тогда либо ставят его (sudo apt install rsyslog), либо читают журнал через journalctl, как выше. Отдельный cron.log по умолчанию тоже не создается: в стандартной настройке rsyslog строка для cron закомментирована, ее можно включить и перезапустить rsyslog.

Задание не работает: что проверить

Идите сверху вниз: первые строки отсекают самые частые причины.

Что видите Вероятная причина Что проверить
Команда работает в терминале, из cron нет Другое окружение: PATH, относительные пути, [[ ]] под sh Полные пути, PATH и SHELL в crontab, запуск через env -i
В журнале нет записи о запуске Строка не принята, служба не работает, задание в другом crontab systemctl status cron, crontab -l, journalctl -u cron.service
Запись о запуске есть, результата нет Ошибка в самой команде, вывод потерян Перенаправление >> файл 2>&1, права на каталог лога
Запись с датой в имени файла не создается Неэкранированный % Замените % на \%
Сработало не в то время или не в те дни Правило «или» для дней, часовой пояс, смена времени Поля дня месяца и недели, timedatectl
Нет /var/log/syslog Не установлен rsyslog journalctl -u cron.service или установка rsyslog
Копии задания накладываются друг на друга Задание дольше интервала Блокировка через flock, см. ниже

Как не запустить задание дважды

Если скрипт работает дольше интервала между запусками, cron стартует вторую копию, пока не закончилась первая. Для резервных копий и синхронизации это обычно плохо. Защищает утилита flock:

*/5 * * * * /usr/bin/flock -n /tmp/sync.lock /opt/scripts/sync.sh

Ключ -n означает «не ждать». Если блокировка занята, flock сразу завершается с кодом 1, и вторая копия не стартует. Файл блокировки создается сам, если его нет. Держите его на локальном диске: на сетевых файловых системах вроде NFS и CIFS flock может не работать.

Итоги

Cron хорош для простого случая: одна команда в заданное время. Новое расписание сначала проверяйте на коротком интервале с записью в лог, и только потом ставьте настоящее. Когда нужно догнать запуск, пропущенный из-за простоя сервера, или дождаться другой службы, смотрите в сторону systemd timers: у них для этого есть свои средства.

Где отладить расписание, не трогая рабочий сервер

Если заданиями управляет компания, расписание удобнее сначала проверить на отдельной машине. В LanCloud для этого можно взять облачный сервер Cloud Server на Linux: для компаний первый месяц тестирования бесплатный.

Оформление заказа
Мы, ООО «ЛанКей ИТ», гарантируем конфиденциальность получаемой нами информации. Обработка персональных данных осуществляется в целях исполнения заказов, договоров и пр. услуг в соответствии с «Политикой конфиденциальности персональных данных».
Отправляем...
Оформление заказа

0.00 ₽ /мес.

Количество лицензий:

Мы, ООО «ЛанКей ИТ», гарантируем конфиденциальность получаемой нами информации. Обработка персональных данных осуществляется в целях исполнения заказов, договоров и пр. услуг в соответствии с «Политикой конфиденциальности персональных данных».
Отправляем...