LinuxRuLinux без лишней теории
Планировщик задач

Cron и crontab в Linux: как настроить задания по расписанию

Редакция LinuxRu7 мин чтенияИнструкции

Cron в Linux запускает команды по расписанию: задание добавляют через crontab -e строкой из пяти полей времени и команды, например 30 3 * * * /usr/local/bin/backup.sh для запуска каждый день в 3:30. Ниже синтаксис, готовые примеры, где искать логи и почему скрипт из терминала не работает в cron. В конце показан systemd timer как современная альтернатива.

Cron и crontab в Linux: как настроить задания по расписанию
Фото: The GNOME Project, GPL, Wikimedia Commons
Содержание
  1. Как устроен cron
  2. Установка
  3. Команда crontab
  4. Синтаксис
  5. Примеры
  6. Не срабатывает
  7. Логи
  8. Systemd timers
  9. Частые вопросы

Как устроен cron и где лежат задания

Cron это демон, который раз в минуту просматривает таблицы заданий и запускает те, чьё время пришло. Таблиц несколько, и путаница между ними порождает половину вопросов на форумах.

  • Пользовательские crontab. У каждого пользователя своя таблица, её редактируют командой crontab -e. Хранятся в каталоге /var/spool/cron/ (подкаталог зависит от дистрибутива), но руками эти файлы не правят.
  • Системный /etc/crontab и каталог /etc/cron.d/. Здесь в каждой строке есть дополнительное поле: от имени какого пользователя запускать команду. Сюда кладут свои задания пакеты.
  • Каталоги /etc/cron.hourly, cron.daily, cron.weekly, cron.monthly. В них лежат обычные исполняемые скрипты без расписания. Их запускает run-parts или anacron с нужной периодичностью.

Реализаций демона несколько. В Debian 13 по-прежнему классический пакет cron, а в Ubuntu 26.04 справочная страница cron уже приходит из пакета cronie, который давно используется в Fedora и Arch. Синтаксис crontab у них совпадает, различаются названия пакетов и служб.

ДистрибутивПакетСлужбаЖурнал
Debian 13croncron.servicejournalctl -u cron
Ubuntu 26.04cronieпроверьте через list-unit-filesjournalctl -u и имя службы
Fedora 44croniecrond.servicejournalctl -u crond
Arch Linuxcroniecronie.servicejournalctl -u cronie

Установка и запуск демона

В Debian, Ubuntu и Fedora cron обычно уже установлен и запущен. В Arch Linux его нужно поставить и включить самостоятельно. Точное имя службы в вашей системе показывает первая команда:

systemctl list-unit-files | grep -i cron
# Debian, Ubuntu
sudo apt install cron
# Fedora
sudo dnf install cronie
sudo systemctl enable --now crond
# Arch
sudo pacman -S cronie
sudo systemctl enable --now cronie

Проверить, что демон работает, можно командой systemctl status с именем службы из списка. Если служба в состоянии failed, разберитесь с ней по инструкции о том, как найти и исправить упавшую службу.

Команда crontab: добавить, посмотреть, удалить

# открыть свою таблицу в редакторе
crontab -e
# показать задания
crontab -l
# таблица другого пользователя (нужен root)
sudo crontab -u backup -e
# удалить все свои задания с подтверждением
crontab -i -r

При первом запуске crontab -e в Debian и Ubuntu спросит, каким редактором пользоваться. Новичку проще выбрать nano, основные клавиши описаны в статье про редактор nano. Поменять выбор потом можно командой select-editor или переменной окружения:

EDITOR=nano crontab -e

Будьте осторожны с crontab -r: буква r стоит на клавиатуре рядом с e, и одна опечатка стирает всю таблицу без вопросов. Ключ -i добавляет подтверждение. Надёжная привычка: держать копию таблицы в файле.

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

Сохраняя файл, crontab проверяет синтаксис. Если в строке ошибка, вы увидите сообщение и предложение вернуться к редактированию.

Синтаксис расписания cron

Каждая строка пользовательского crontab состоит из пяти полей времени и команды:

# минута  час  день_месяца  месяц  день_недели  команда
# 0-59     0-23  1-31        1-12   0-7 (0 и 7 = воскресенье)
30 3 * * * /usr/local/bin/backup.sh

В полях допускаются специальные символы:

  • * любое значение;
  • , список: 1,15 означает первое и пятнадцатое число;
  • - диапазон: 1-5 в дне недели означает будни;
  • / шаг: */10 в минутах означает каждые 10 минут.

Вместо пяти полей можно написать сокращение: @reboot (при старте демона), @hourly, @daily, @weekly, @monthly, @yearly.

Одна ловушка стоит отдельного внимания. Если заданы и день месяца, и день недели, cron запускает задание, когда совпало любое из двух условий, а не оба. Строка 0 9 1 * 1 сработает первого числа каждого месяца и вдобавок каждый понедельник. Для условия "первый понедельник месяца" проверку делают внутри команды.

Примеры заданий для crontab

# каждые 15 минут
*/15 * * * * /home/user/bin/check-site.sh
# каждый день в 03:30
30 3 * * * /usr/local/bin/backup.sh
# по будням в 9:00
0 9 * * 1-5 /home/user/bin/report.sh
# каждое воскресенье в 2:00
0 2 * * 0 /usr/bin/find /home/user/tmp -type f -mtime +7 -delete
# первого числа каждого месяца в полночь
0 0 1 * * /usr/local/bin/rotate-archive.sh
# при загрузке системы
@reboot /home/user/bin/start-sync.sh
# не запускать новую копию, пока не закончилась старая
*/5 * * * * /usr/bin/flock -n /tmp/sync.lock /home/user/bin/sync.sh

Последний пример решает частую проблему: долгий скрипт не успевает закончиться к следующему запуску, копии накапливаются и забивают систему. Утилита flock из пакета util-linux просто не даст стартовать второй копии.

Знак процента в crontab означает перевод строки, поэтому команды с date +%F нужно экранировать:

0 1 * * * tar -czf /backup/home-$(date +\%F).tar.gz /home/user

Для серьёзного резервного копирования лучше взять инструмент с дедупликацией и проверкой целостности. Как настроить Borg или Restic и запускать их по расписанию, описано в статье про резервные копии Linux.

Почему в терминале работает, а в cron нет

Это самый частый вопрос про cron. Причина почти всегда в окружении: задание запускается не из вашей оболочки, а с минимальным набором переменных.

  1. PATH урезан. Обычно там только /usr/bin:/bin. Пишите полные пути к программам или задайте PATH в начале таблицы.
  2. Нет рабочего каталога. Задание стартует в домашнем каталоге. Относительные пути в скрипте ломаются, используйте абсолютные или cd в начале.
  3. Нет графической сессии. Программы, которым нужен экран или уведомления, не знают DISPLAY и адрес шины D-Bus.
  4. Скрипт не исполняемый или сохранён в Windows с окончаниями строк CRLF. Проверьте chmod +x и file script.sh.
  5. Неэкранированный процент, о котором шла речь выше.
  6. Точка в имени файла. Файлы вроде backup.sh в /etc/cron.d и /etc/cron.daily Debian пропускает молча. Называйте их без расширения.

Переменные задаются прямо в crontab, перед заданиями:

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=""

Чтобы увидеть окружение cron своими глазами, добавьте временное задание * * * * * env > /tmp/cron-env.txt, подождите минуту и сравните файл с выводом env в терминале. Разница сразу покажет, чего не хватает скрипту. Не забудьте потом удалить строку.

Логи cron и вывод заданий

Сам демон пишет в журнал, когда запускает задание. Посмотреть последние записи:

# Debian
journalctl -u cron --since today
# Fedora
journalctl -u crond --since today
# Arch
journalctl -u cronie --since today
# по тегу, в любом дистрибутиве
journalctl -t CRON -t CROND -t crond --since "1 hour ago"

Но журнал покажет только факт запуска, а не то, что напечатал скрипт. Вывод задания cron пытается отправить почтой владельцу таблицы. На домашнем компьютере почтового сервера обычно нет, и сообщения теряются. Надёжнее перенаправить вывод в файл или в журнал:

# в файл, вместе с ошибками
30 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# в системный журнал с тегом
30 3 * * * /usr/local/bin/backup.sh 2>&1 | logger -t backup

Во втором случае вывод читается командой journalctl -t backup. Файлы логов не забывайте ротировать, иначе через год они займут заметное место.

Systemd timers как альтернатива cron

В системах с systemd то же самое умеют таймеры. Они многословнее, зато каждый запуск попадает в журнал вместе с выводом, задание можно запустить вручную через systemctl start, а пропущенный из-за выключенного компьютера запуск выполнится при включении. Задача состоит из двух файлов.

# /etc/systemd/system/backup.service
[Unit]
Description=Ночная резервная копия

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Запуск backup.service каждый день

[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
RandomizedDelaySec=10min

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers
# проверить выражение расписания
systemd-analyze calendar "Mon..Fri *-*-* 09:00"

Persistent=true отвечает за догоняющий запуск, а RandomizedDelaySec разносит задания во времени, чтобы они не стартовали одновременно. Вывод скрипта смотрят через journalctl -u backup.service. Основы работы с юнитами есть в статье про systemctl, все форматы OnCalendar описаны в справке systemd.time.

Что выбрать? Для пары простых заданий на сервере или для привычных однострочников cron удобнее. Если важна гарантия выполнения после простоя ноутбука, журналы и зависимости от сети или дисков, берите таймер.

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

Как добавить задание в cron?

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

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

В журнале systemd: journalctl -u cron в Debian, journalctl -u crond в Fedora, journalctl -u cronie в Arch. Вывод самих заданий лучше перенаправлять в файл или logger.

Как запускать задание каждые 5 минут?

Используйте шаг в поле минут: */5 * * * * /путь/к/скрипту.

Почему скрипт работает вручную, но не в cron?

В cron урезан PATH, нет графической сессии и рабочего каталога. Пишите полные пути, задайте PATH в crontab и экранируйте знак процента.

Что лучше: cron или systemd timer?

Cron проще для коротких заданий. Таймер systemd выполняет пропущенные запуски, пишет вывод в журнал и умеет зависимости, поэтому лучше для ноутбуков и важных задач.

Документация и источники

Читайте также

Команды проверены на актуальных версиях дистрибутивов на момент обновления. Перед изменением системных настроек сделайте резервную копию.