Планирование задач в Linux: сравнение cron и systemd timer

В администрировании Linux «когда» выполнение задачи так же важно, как и «что» она делает. Самый старый инструмент – cron, а в современных дистрибутивах всё чаще используют systemd timer. В этой статье мы сравним оба подхода и разберём, в каких ситуациях лучше выбрать каждый из них.


1. Зачем сравнивать cron и systemd timer?



На большинстве Linux‑серверов встречаются такие требования:

  • ежедневный запуск резервного копирования в 3 :00 утра
  • проверка состояния каждые 5 минут
  • еженедельная архивация логов в воскресенье
  • инициализационная задача, которая должна выполниться один раз через минуту после загрузки

Ранее все это решали через cron, но теперь, когда большинство дистрибутивов используют systemd как init‑систему, «таймерные юниты» становятся мощной альтернативой.


2. Основы cron

2.1 Что такое cron?

cron – старый Unix‑/Linux‑планировщик. Он запускает команды по заданному расписанию, а настройки хранятся в файлах crontab.

2.2 Где находятся настройки cron?

  • Системные: /etc/crontab, /etc/cron.d/
  • Пользовательские: редактируются через crontab -e

Например, ежедневный запуск резервного скрипта в 3 :00 утра:

0 3 * * * /usr/local/bin/backup.sh

Поля означают:

минуты часы день месяца месяц день недели команда
0      3     *     *     *     /usr/local/bin/backup.sh

2.3 Плюсы cron

  • Долгий срок эксплуатации и проверка
  • Универсальность: работает почти на всех Unix‑системах
  • Простая синтаксис и множество примеров
  • Поддержка даже в системах без systemd

2.4 Ограничения cron

  • Отсутствует явная связь с сервисами
  • Логирование и статус распределены (syslog, почта и т.д.)
  • Сложно управлять зависимостями (например, запуск после сети)
  • Относительные интервалы («через 5 минут после загрузки») требуют трюков

3. Основы systemd timer



3.1 Что такое systemd timer?

systemd timer – это «таймерный юнит» systemd, который запускает другой юнит‑сервис по заданным условиям (время, задержка после загрузки и т.д.).

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

  • myjob.service – определяет, что именно выполняется
  • myjob.timer – определяет, когда это происходит

3.2 Пример сервиса + таймера

Ежедневный запуск резервного копирования:

(1) Сервисный юнит: /etc/systemd/system/backup.service

[Unit]
Description=Daily backup job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

(2) Таймерный юнит: /etc/systemd/system/backup.timer

[Unit]
Description=Run daily backup at 3:00

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

Активация:

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

3.3 Плюсы systemd timer

  • Явная связь с сервисом – легко понять, какой сервис запущен
  • Логирование через journalctl -u backup.service
  • Гибкие триггеры:
  • OnCalendar= – похож на cron
  • OnBootSec= – X секунд после загрузки
  • OnUnitActiveSec= и OnUnitInactiveSec= – интервалы после последнего запуска
  • Управление зависимостями: After=network-online.target и т.д.
  • Интеграция с ecosystem systemd: systemctl list-timers, systemctl status

3.4 Минусы systemd timer

  • Крутая кривая обучения (нужно два файла)
  • Зависимость от systemd – не подходит для старых систем или non‑systemd окружений
  • Для простых однострочных задач может показаться избыточным

4. Сравнение функций

Параметр cron systemd timer
Местоположение /etc/crontab, crontab -e /etc/systemd/system/*.service/*.timer
Цель произвольная команда сервис systemd
Выражение времени cron‑выражение (5 полей) OnCalendar, OnBootSec и др.
Относительные интервалы ограничено, требует трюков OnBootSec, OnUnitActiveSec и т.д.
Управление ошибками вручную через параметры юнита
Логи syslog, почта journalctl
Зависимости нет After=, Requires=
Интеграция низкая высокая
Переносимость высокая зависит от systemd

5. Практические примеры

5.1 Ежедневный резервный копирование: cron vs timer

cron

0 3 * * * /usr/local/bin/backup.sh

systemd timer

# backup.service
[Unit]
Description=Daily backup job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# backup.timer
[Unit]
Description=Run daily backup at 3:00

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

5.2 Запуск один раз через 5 минут после загрузки

В cron это обычно делается через @reboot + sleep или rc.local.

systemd timer

# init-job.service
[Unit]
Description=Run custom init job after boot

[Service]
Type=oneshot
ExecStart=/usr/local/bin/init-job.sh
# init-job.timer
[Unit]
Description=Run init job 5 minutes after boot

[Timer]
OnBootSec=5min
AccuracySec=1min

[Install]
WantedBy=timers.target

После загрузки через 5 минут будет запущен init-job.service.


6. Как выбрать?

6.1 Когда можно продолжать использовать cron

  • Уже есть работающие cron‑задания, и интеграция с systemd не требуется
  • Небольшой сервер с несколькими простыми задачами
  • Окружения без systemd (контейнеры, BSD, старые ОС)

6.2 Когда стоит перейти на systemd timer

  • Большинство сервисов уже управляются systemd
  • Нужно централизованное логирование и статус
  • Требуются относительные интервалы (после загрузки, после последнего запуска)
  • Необходима зависимость от других сервисов (сеть, файловая система)
  • Требуется наблюдаемость и консистентность в CI/CD и продакшене

7. Советы по миграции из cron в systemd timer

  1. Соберите список текущих cron‑заданий * crontab -l * /etc/crontab, /etc/cron.d/*
  2. Разделите задачу на сервис + таймер * Что запускается? → .service * Когда запускается? → .timer
  3. Преобразуйте выражения времени * 0 3 * * *OnCalendar=*-*-* 03:00:00 * */5 * * * *OnCalendar=*:0/5
  4. Проверьте вручную * systemctl start myjob.service * systemctl start myjob.timer и systemctl list-timers
  5. Отключите старый cron * После подтверждения стабильности закомментируйте или удалите cron‑строку

8. Итоги: coexistence is possible

  • cron остаётся простым и переносимым планировщиком
  • systemd timer предоставляет сервис‑ориентированное управление, наблюдаемость и гибкие триггеры

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

image