Будни ИТишника заметки о Linux и инфраструктуре

Таймеры systemd вместо cron: что удобнее на практике

14.09.2026 · systemd, автоматизация

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

Минимальный пример

Задача — раз в сутки обновлять список пакетов и складывать в файл.

[Unit]
Description=Daily apt update cache
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/apt-get update
Nice=10
IOSchedulingClass=idle

Файл: /etc/systemd/system/apt-update.service.

[Unit]
Description=Run apt-update daily

[Timer]
OnCalendar=*-*-* 04:20:00
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target

Файл: /etc/systemd/system/apt-update.timer. Затем:

systemctl daemon-reload
systemctl enable --now apt-update.timer
systemctl list-timers apt-update.timer

Что мне нравится

  • Логи. journalctl -u apt-update сразу показывает и stdout, и код возврата. С cron приходится помнить про MAILTO и редиректы.
  • Persistent=true — если сервер был выключен в момент запуска, задача выполнится при следующей загрузке. У cron аналога нет, нужен anacron.
  • RandomizedDelaySec — размывает нагрузку, когда десяток серверов запускают одно и то же в одну секунду.

Что неудобно

Порог входа выше: вместо одной строки в crontab — два файла. Для одноразовой задачи «запустить через 10 минут» cron или systemd-run --on-active=10m всё ещё быстрее.

И ещё: OnCalendar понимает далеко не все «человеческие» форматы. Проверять синтаксис удобно так:

systemd-analyze calendar "*-*-* 04:20:00"

Перенос с cron без сюрпризов

Главная разница — окружение. Cron запускает задачу с почти пустым PATH и без вашего профиля. В юните systemd PATH тоже минимальный, поэтому либо указывайте абсолютные пути, либо задавайте Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin.

Проверка ровно та же, что и с cron: запустить руками через systemctl start apt-update.service и посмотреть journalctl -u apt-update -n 50.