Инструкция

Crontab: примеры расписания задач в Linux, синтаксис и типичные ошибки

Обновлено: · Skillaria.Top

Crontab — это таблица расписания, по которой демон cron запускает команды: каждая строка состоит из пяти полей времени (минута, час, день месяца, месяц, день недели) и команды, например */5 * * * * /opt/backup.sh запускает скрипт каждые 5 минут. Редактируется таблица командой crontab -e, а большинство проблем связано с урезанным окружением cron: указывайте полные пути и перенаправляйте вывод в лог.

Cron — стандартный планировщик задач в Linux: демон cron раз в минуту читает таблицы расписания (crontab) и запускает команды, время которых пришло. Так делают резервные копии по ночам, чистят временные файлы, обновляют сертификаты и отправляют отчёты. Ниже — синтаксис, crontab примеры на типовые случаи и разбор ошибок, из-за которых задача «молча» не выполняется.

Как открыть и редактировать crontab

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

КомандаЧто делает
crontab -eоткрыть свою таблицу в редакторе (при первом запуске предложит выбрать редактор)
crontab -lпоказать текущую таблицу
crontab -rудалить таблицу целиком, без подтверждения
crontab -i -rудалить с подтверждением (Debian/Ubuntu, RHEL)
sudo crontab -u alice -eредактировать таблицу другого пользователя
crontab файлзаменить таблицу содержимым файла

После сохранения crontab -e проверяет синтаксис и пишет crontab: installing new crontab. Если в строке ошибка, вы увидите errors in crontab file, can't install и предложение отредактировать снова. Перезапускать демон не нужно — изменения подхватываются автоматически.

Будьте осторожны с -r: буквы e и r на клавиатуре рядом, а резервной копии таблицы нет. Полезная привычка — держать бэкап:

crontab -l > ~/crontab.bak
# восстановить
crontab ~/crontab.bak

Синтаксис crontab: пять полей времени

Каждая строка задачи выглядит так:

# ┌───────── минута (0–59)
# │ ┌─────── час (0–23)
# │ │ ┌───── день месяца (1–31)
# │ │ │ ┌─── месяц (1–12 или jan–dec)
# │ │ │ │ ┌─ день недели (0–7 или sun–sat; 0 и 7 — воскресенье)
# │ │ │ │ │
  * * * * * команда

В каждом поле можно использовать специальные символы:

СимволЗначениеПример
*любое значение* * * * * — каждую минуту
,список0 9,18 * * * — в 9:00 и 18:00
-диапазон0 9-18 * * * — каждый час с 9 до 18
/шаг*/15 * * * * — каждые 15 минут

Шаг можно сочетать с диапазоном: 0 8-20/2 * * * — каждые два часа с 8 до 20 (8, 10, …, 20). Время берётся по часовому поясу системы — проверьте его командой timedatectl.

Crontab примеры на каждый день

РасписаниеСтрока crontab
каждую минуту* * * * *
каждые 5 минут*/5 * * * *
каждые 30 минут*/30 * * * * или 0,30 * * * *
каждый час в начале часа0 * * * *
каждые 6 часов0 */6 * * *
каждый день в 3:000 3 * * *
каждый день в 23:4545 23 * * *
по будням в 9:000 9 * * 1-5
по выходным в полдень0 12 * * 6,0
по понедельникам в 8:3030 8 * * 1
1-го числа каждого месяца в 00:000 0 1 * *
раз в квартал0 0 1 1,4,7,10 *
раз в год, 1 января0 0 1 1 *
каждые 10 минут в рабочее время*/10 9-18 * * 1-5

Полная строка задачи — расписание плюс команда:

# резервная копия базы каждую ночь в 3:00
0 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1

# чистка временных файлов старше 7 дней по воскресеньям
0 4 * * 0 /usr/bin/find /tmp/app -type f -mtime +7 -delete

# проверка сайта каждые 5 минут
*/5 * * * * /usr/bin/curl -fsS https://example.com/health > /dev/null || /usr/local/bin/alert.sh

Специальные строки @reboot, @daily и другие

Вместо пяти полей можно написать короткий псевдоним:

ПсевдонимЭквивалент
@rebootодин раз при старте демона cron (после загрузки системы)
@hourly0 * * * *
@daily / @midnight0 0 * * *
@weekly0 0 * * 0
@monthly0 0 1 * *
@yearly / @annually0 0 1 1 *
@reboot /home/alice/bin/start-tunnel.sh >> /home/alice/tunnel.log 2>&1

Для сервисов, которые должны работать постоянно и перезапускаться при падении, @reboot — слабое решение: лучше оформить юнит systemd с Restart=on-failure.

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

Минимальная единица cron — одна минута. Если нужно чаще, есть два приёма. Первый — несколько строк со сдвигом через sleep:

* * * * * /opt/check.sh
* * * * * sleep 30; /opt/check.sh

Второй, более правильный — таймер systemd с OnUnitActiveSec=30s. Если задача выполняется чаще раза в минуту, это обычно уже работа для демона или таймера, а не для cron.

Системный crontab: /etc/crontab и /etc/cron.d

Кроме пользовательских таблиц есть системные. Их формат отличается: между временем и командой стоит имя пользователя, от которого запускать команду.

# /etc/cron.d/certbot-renew
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root certbot renew --quiet

Что где лежит:

  • /etc/crontab — главная системная таблица; в Debian/Ubuntu из неё запускаются каталоги ниже.
  • /etc/cron.d/ — отдельные файлы с задачами, удобно класть их пакетами или через Ansible.
  • /etc/cron.hourly/, cron.daily/, cron.weekly/, cron.monthly/ — сюда кладут исполняемые скрипты без расписания; их запускает run-parts (или anacron).

Подвох с run-parts: в Debian и Ubuntu он пропускает файлы, в имени которых есть точка. Скрипт backup.sh в /etc/cron.daily/ не запустится — назовите его backup. Проверить, что будет выполнено, можно командой run-parts --test /etc/cron.daily.

Файлы в /etc/cron.d/ должны принадлежать root, не быть доступными на запись группе и остальным и оканчиваться переводом строки — иначе cron их проигнорирует.

Окружение cron: PATH, SHELL и переменные

Главная причина фразы «в терминале работает, а в cron нет» — окружение. Cron запускает команды через /bin/sh, без вашего .bashrc и .profile, с минимальным PATH (обычно /usr/bin:/bin). Поэтому docker, node или php из /usr/local/bin могут быть просто не найдены.

Переменные можно задать в начале таблицы:

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
CRON_TZ=Europe/Moscow

0 6 * * * cd /srv/app && ./report.sh
  • MAILTO — куда отправлять вывод задачи; MAILTO="" отключает письма.
  • CRON_TZ — часовой пояс для расписания (поддерживается cronie в RHEL/Fedora; в Debian-версии cron эта переменная не работает).
  • Подстановок вроде $HOME/bin в значениях переменных нет — пишите пути целиком.

Самый надёжный вариант — указывать в задаче абсолютные пути ко всем программам и файлам, а в скриптах первой строкой ставить shebang: #!/bin/bash.

Где смотреть логи cron

Cron записывает в журнал сам факт запуска задачи, но не её вывод:

# Debian/Ubuntu
grep CRON /var/log/syslog
# через systemd-journald
journalctl -u cron --since today      # Debian/Ubuntu
journalctl -u crond --since today     # RHEL, Fedora, Rocky
# RHEL без journald
tail -f /var/log/cron

Строка запуска выглядит примерно так:

Oct 14 03:00:01 web1 CRON[21544]: (root) CMD (/usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1)

Чтобы видеть, что задача напечатала и с какой ошибкой упала, перенаправляйте и stdout, и stderr в файл: >> /var/log/job.log 2>&1. Без этого вывод уходит письмом через локальную почту, а если почтовый агент не установлен — теряется (в журнале появится No MTA installed, discarding output).

Почему cron не запускает задачу: типичные ошибки

Команда не найдена

Симптом: в логе задачи command not found. Причина — урезанный PATH. Решение: полный путь к программе (which docker подскажет его) или строка PATH= в начале таблицы.

Знак процента в команде

В crontab символ % означает перевод строки: всё после первого % передаётся команде на стандартный ввод. Поэтому классическая строка с датой в имени файла ломается:

# неправильно — команда обрежется на первом %
0 2 * * * tar czf /backup/site-$(date +%F).tar.gz /var/www
# правильно — экранировать
0 2 * * * tar czf /backup/site-$(date +\%F).tar.gz /var/www

Ещё проще — вынести логику в скрипт, где % не нужно экранировать.

Скрипт не исполняемый или с неправильными переводами строк

Ошибка Permission denied значит, что у файла нет бита x: выполните chmod +x script.sh или запускайте явно, /bin/bash /opt/script.sh. Если скрипт писали в Windows, переводы строк CRLF дают странную ошибку /bin/bash^M: bad interpreter — исправляется командой sed -i 's/\r$//' script.sh или dos2unix.

Относительные пути и рабочий каталог

Задача стартует в домашнем каталоге пользователя. Если скрипт читает ./config.ini, он будет искать его в ~. Делайте cd /srv/app && перед командой или используйте абсолютные пути внутри скрипта.

День месяца и день недели одновременно

Если заданы оба поля, cron срабатывает, когда совпадает любое из них, а не оба сразу. Строка 0 9 13 * 5 запустится 13-го числа и каждую пятницу, а не только в пятницу 13-е. Нужное условие проверяют внутри команды:

0 9 13 * * [ "$(date +\%u)" = 5 ] && /opt/friday13.sh

Задачи накладываются друг на друга

Если резервная копия идёт дольше интервала, следующий запуск стартует поверх предыдущего. Защита — блокировка через flock:

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

С флагом -n второй экземпляр сразу завершится, если первый ещё работает.

Демон cron не запущен

Проверьте systemctl status cron (в RHEL — crond). В минимальных образах, например в Docker-контейнерах, демона cron нет вовсе — задачи в crontab там просто некому выполнять.

Как отладить задачу cron

Запустите команду в окружении, максимально похожем на cron:

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

Если здесь возникает ошибка — она же будет и в cron. Временно поставьте расписание * * * * *, перенаправьте вывод в файл и следите за ним через tail -f. Для проверки самого расписания помогают онлайн-калькуляторы выражений cron, но последнее слово — за журналом системы.

Кто может пользоваться cron: cron.allow и cron.deny

Доступ ограничивают файлы /etc/cron.allow и /etc/cron.deny. Если существует cron.allow, crontab доступен только перечисленным в нём пользователям. Если его нет, а есть cron.deny, — всем, кроме перечисленных. Пользователь из запрещённых при crontab -e получит сообщение You (bob) are not allowed to use this program.

Итог

Crontab — это строки из пяти полей времени и команды: */5 * * * * — каждые 5 минут, 0 3 * * * — каждую ночь, 0 9 * * 1-5 — по будням. Редактируйте таблицу через crontab -e, указывайте абсолютные пути, экранируйте %, пишите вывод в лог и защищайте долгие задачи через flock. Разобранных crontab примеров хватает для большинства серверных задач, а автоматизация и планирование задач подробно разобраны на практике в курсе по Linux.

Частые вопросы

Чем cron отличается от anacron?

Cron запускает задачи в точное время и пропускает их, если компьютер был выключен. Anacron гарантирует, что ежедневные, еженедельные и ежемесячные задачи выполнятся после включения, поэтому подходит для ноутбуков и десктопов.

Что лучше: cron или таймеры systemd?

Cron проще и есть почти везде. Таймеры systemd дают логи в journalctl, зависимости, ограничение ресурсов и параметр Persistent=true для пропущенных запусков, поэтому на современных серверах их всё чаще выбирают для важных задач.

Где физически хранится crontab пользователя?

В Debian и Ubuntu — в /var/spool/cron/crontabs/имя, в RHEL и Fedora — в /var/spool/cron/имя. Редактировать эти файлы напрямую не стоит, используйте crontab -e.

Как временно отключить задачу в crontab?

Закомментируйте строку символом # в начале через crontab -e. Чтобы отключить все задачи пользователя, сохраните таблицу в файл командой crontab -l и затем удалите её через crontab -r.

Как запустить задачу в последний день месяца?

Отдельного поля для этого нет. Запускайте задачу 28–31 числа и проверяйте, что завтра первое число: 0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = 01 ] && /opt/job.sh.

Разберите тему на видео

Эта тема подробно разобрана с практикой в курсе «Linux: с нуля до уверенного администрирования».

Перейти к курсу