Рабочие заметки

systemd timers вместо cron

Я долго держался за cron: он в голове, он везде. Сломало меня то, что задание молча не отработало ночью, а узнал я об этом через неделю. В cron нет ни состояния, ни внятного «покажи последний запуск».

Шаблон

Две единицы. Сервис описывает, что делать:

# /etc/systemd/system/report.service
[Unit]
Description=Ночной отчёт
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=reports
ExecStart=/opt/reports/bin/build --since=yesterday
TimeoutStartSec=30min
Nice=10
IOSchedulingClass=idle

Таймер — когда:

# /etc/systemd/system/report.timer
[Unit]
Description=Запуск ночного отчёта

[Timer]
OnCalendar=*-*-* 03:20:00
RandomizedDelaySec=10m
Persistent=true
AccuracySec=1m

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now report.timer

Ради чего всё это

Мелочи, на которые я наступил

Имена должны совпадать. report.timer по умолчанию запускает report.service. Если имена разные, нужен явный Unit= в секции [Timer].

Проверка выражения. Формат OnCalendar не совпадает с cron. Перед тем как включать, стоит прогнать:

systemd-analyze calendar 'Mon *-*-* 06:00:00' --iterations=3

Перекрытие запусков. systemd не запустит второй экземпляр oneshot-сервиса, пока работает первый — он просто пропустит срабатывание. Для cron это была отдельная возня с lock-файлами, здесь поведение по умолчанию правильное.

Часовой пояс. OnCalendar считает по локальному времени хоста. Если хосты в разных зонах, честнее сразу писать OnCalendar=*-*-* 03:20:00 UTC.


← ко всем записям