Bash + systemd timers вместо cron
Cron жил с 70-х, и его ограничения это подтверждают. Переезжаем на systemd timers — без боли.
Cron — это надёжно, предсказуемо, работает везде. Но у него есть три вещи, которые меня раздражают:
- Нет нормального логирования. Письмо root'у — это не лог.
- Нет зависимостей. «Сделай X после Y, но только если Y успешно» — это уже конструкция из if'ов в самом скрипте.
- Нет возможности посмотреть «а когда оно в последний раз отрабатывало и сколько заняло».
Systemd timers решают все три.
Минимальный пример
Сервис — обычный unit, который мы потом дёрнем по таймеру:
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
StandardOutput=journal
StandardError=journal
Таймер:
# /etc/systemd/system/backup.timer
[Unit]
Description=Nightly backup
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
RandomizedDelaySec=15min
[Install]
WantedBy=timers.target
Включаем:
systemctl daemon-reload
systemctl enable --now backup.timer
Что в итоге получаем
- Логи в journalctl:
journalctl -u backup.service --since today— со всеми stdout/stderr скрипта. - Зависимости: в
[Unit]секции можно указатьAfter=,Requires=,Wants=. - История:
systemctl list-timers backup.timer— показывает last/next run и сколько заняло. - Persistent=true — если машина была выключена в момент срабатывания, таймер отработает при загрузке.
- RandomizedDelaySec — разносит запуск по времени, чтобы все 30 сервисов не стартовали ровно в 03:00.
Когда cron всё-таки лучше
Если нужно править расписание раз в неделю на 5 минут — cron быстрее. Если задача — «каждые 5 минут сделать HTTP GET на /health» и всё — тоже cron. Systemd timers окупаются там, где задача сложнее, чем одна команда, и где вы хотите видеть, что происходит.