Назад до блога

Cron чи таймери systemd: що обрати?

11 вересня 2026 р.

На сучасному дистрибутиві використовуйте таймер systemd для всього свого, а cron лишіть для однорядкових задач користувача і серверів, які ви не будували. Таймери логують кожен запуск у журнал, уміють наздоганяти розклади, пропущені поки машина була вимкнена, і залежать від тих самих юніт-файлів, що й уся система. Cron виграє лаконічністю — один рядок crontab -e проти двох юніт-файлів — і досі єдиний планувальник, гарантований у мінімальних контейнерах та екзотичних Unix-машинах. Пастка: cron мовчить при збої. Якщо ваша задача впаде о третій ночі, cron надішле листа у локальну скриньку, яку ніхто не читає, тоді як таймер дає journalctl -u mytimer.service з повним виводом. Нижче: справжні відмінності, тестування кожного, чому таймер може не спрацювати, і таблиця рішень.

У чому різниця між cron і таймером systemd?

Cron — демон, що читає таблицю рядків: п’ять часових полів і команда — і запускає кожну команду, коли годинник збігається. Це вся модель. Поняття «задача» як об’єкта немає: жодного юніта, статусу, залежностей чи власного запису в лог.

Таймер systemd — юніт-файл (foo.timer), що вмикає інший юніт-файл (foo.service), коли його розклад збігається. Задача — об’єкт першого класу зі start, status, логами і трекінгом збоїв, як усякий сервіс. Розклад — або календарний (у стилі cron), або монотонний (OnBootSec=15min, який годинникові стрибки не обдурять).

Практичні наслідки:

  • Логування: таймери пишуть stdout/stderr у журнал по-юнітно; cron в кращому разі шле листа локальному користувачу.
  • Пропущені запуски: таймер з Persistent=true один раз запуститься на boot, якщо розклад пропало; cron просто скіпне.
  • Залежності: таймери вміють чекати network-online.target чи точок монтування; cron змушує писати retry-логіку у скрипті власноруч.
  • Синтаксис: cron — один рядок; таймер — два файли. Це вся ціна переходу.

Який синтаксис розкладу простіший — crontab чи OnCalendar?

П’ять полів cron — компактний інкумбент: */15 * * * * — це кожні 15 хвилин, і більшість адмінів читають це зі сну. OnCalendar= у systemd багатослівніший, але строго виразніший, і systemd-analyze calendar розкаже наступні запуски ще до збереження — у cron еквівалента dry-run немає.

# cron: щодня о 03:30
30 3 * * * /usr/local/bin/backup.sh

# systemd: той самий розклад, перевірний до збереження
systemd-analyze calendar "*-*-* 03:30:00"
# -> Next elapse: Fri 2026-09-11 03:30:00 ...

OnCalendar вміє те, що cron чесно не виражає охайно: Mon..Fri *-*-* 09..17:00:00 (робочі дні, бізнес-години), або *:0/15 з RandomizedDelaySec=10m, щоб тисяча машин не били по серверу в одну мить.

Як протестувати таймер systemd без очікування?

Три команди відповідають на все. Список того, що заплановано і коли наступного разу, запуск задачі руками точно так, як зробив би таймер, і читання його логів:

systemctl list-timers --all                 # кожен таймер, наступний + минулий запуск
sudo systemctl start backup.service         # запустити задачу зараз, той самий юніт
journalctl -u backup.service -f             # дивитися вивід наживо

Зверніть увагу на поділ: systemctl start backup.timer заряджає розклад; сервіс — це сама задача. Якщо list-timers показує ваш таймер, systemctl status backup.service зелений, а журнал показує ваш вивід — ланцюжок працює цілком.

Як запустити cron-задачу вручну?

Cron-задачі працюють зі стриженим середовищем, тому «в моєму шеллі працює, у cron падає» — цілий літературний жанр багів. Щоб відтворити cron вірно, запустіть команду через sh з тим середовищем, яким користувався б cron:

crontab -l                                  # підтвердіть точний рядок
env -i SHELL=/bin/sh PATH=/usr/bin:/bin sh -c '/usr/local/bin/backup.sh'
grep CRON /var/log/syslog | tail            # а cron його взагалі запускав? (Debian/Ubuntu)
journalctl -u cron -n 20                    # те саме на systemd-дистрибутивах

Рядок env -i — чесний ручний тест: голе середовище з дефолтним PATH cron. Більшість тихих збоїв cron — голий PATH чи неекранований % у команді (cron трактує % як новий рядок), і обидва виявляються миттєво.

Чому мій таймер systemd не спрацьовує?

Чотири причини покривають майже кожен випадок, у порядку перевірки:

  1. Імена сервісу і таймера не збігаються. foo.timer вмикає foo.service — одруківка в OnFailure чи перейменований юніт означає, що таймер «стріляє» в нікуди. systemctl cat foo.timer показує, куди він цілиться.
  2. Таймер відредаговано, але не перечитано. Після зміни юніт-файла: sudo systemctl daemon-reload && sudo systemctl restart foo.timer. Без цього новий розклад не живий.
  3. Persistent=true без очікуваної семантики OnCalendar — або ви дивитеся systemctl status foo.timer (завжди active, навіть коли спить) замість list-timers.
  4. Сервіс, який він вмикає, падає миттєво, тож таймер виглядає мертвим. journalctl -u foo.service --since -1h покаже падіння, яке ховає list-timers.

А коли вже дивитеся в логи, шпаргалка journalctl покриває фільтри (-u, --since, -f), які це роблять швидким.

Cron чи таймери systemd: таблиця рішень

cronтаймер systemd
Налаштуванняодин рядок crontabдва юніт-файли
Логуваннялокальна пошта, зазвичай непрочитанажурнал, по юнітах
Пропущений запуск (машина вимкнена)скіпнутоодин запуск з Persistent=true
Залежності / порядокнема — DIY у скриптіповні юніт-залежності
Випадкова затримкаDIY через $RANDOMRandomizedDelaySec=
Тест/dry-run розкладуніsystemd-analyze calendar
Є всюдитак — контейнери, BSD, embeddedпотребує systemd (PID 1)
Задачі користувача без rootcrontab -eюніти systemd --user

Правила великого пальця: ставити задачу на власну systemd-машину → таймер. Швидке особисте нагадування чи чужа машина → cron. Що-небудь із залежностями, ретраями чи потребою знати, чи воно справді виконалося → таймер, завжди. Типовий патерн — таймер із задачею обслуговування, скажімо, нічний rsync-бекап, де Persistent=true гарантує, що бекап станеться, навіть якщо машина спала в заплановану хвилину — чого cron просто не вміє.

— mrsaynothing

— mrsaynothing

Польові нотатки про ШІ, Linux і self-hosting.

Обговорити пост на dev.to dev.to ↗

Наступний гайд — на email

Один лист на пост. Полагодили — і далі.

self-hosted · без третіх сторін · відписка в один клік

що це таке?

llama.cpp чи Ollama: що запускати у 2026 році?

Читається добре? Таке я будую за гроші. найміть мене