На сучасному дистрибутиві використовуйте таймер 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 не спрацьовує?
Чотири причини покривають майже кожен випадок, у порядку перевірки:
- Імена сервісу і таймера не збігаються.
foo.timerвмикаєfoo.service— одруківка вOnFailureчи перейменований юніт означає, що таймер «стріляє» в нікуди.systemctl cat foo.timerпоказує, куди він цілиться. - Таймер відредаговано, але не перечитано. Після зміни юніт-файла:
sudo systemctl daemon-reload && sudo systemctl restart foo.timer. Без цього новий розклад не живий. Persistent=trueбез очікуваної семантикиOnCalendar— або ви дивитесяsystemctl status foo.timer(завжди active, навіть коли спить) замістьlist-timers.- Сервіс, який він вмикає, падає миттєво, тож таймер виглядає мертвим.
journalctl -u foo.service --since -1hпокаже падіння, яке ховаєlist-timers.
А коли вже дивитеся в логи, шпаргалка journalctl покриває фільтри (-u, --since, -f), які це роблять швидким.
Cron чи таймери systemd: таблиця рішень
| cron | таймер systemd | |
|---|---|---|
| Налаштування | один рядок crontab | два юніт-файли |
| Логування | локальна пошта, зазвичай непрочитана | журнал, по юнітах |
| Пропущений запуск (машина вимкнена) | скіпнуто | один запуск з Persistent=true |
| Залежності / порядок | нема — DIY у скрипті | повні юніт-залежності |
| Випадкова затримка | DIY через $RANDOM | RandomizedDelaySec= |
| Тест/dry-run розкладу | ні | systemd-analyze calendar |
| Є всюди | так — контейнери, BSD, embedded | потребує systemd (PID 1) |
| Задачі користувача без root | crontab -e | юніти systemd --user |
Правила великого пальця: ставити задачу на власну systemd-машину → таймер. Швидке особисте нагадування чи чужа машина → cron. Що-небудь із залежностями, ретраями чи потребою знати, чи воно справді виконалося → таймер, завжди. Типовий патерн — таймер із задачею обслуговування, скажімо, нічний rsync-бекап, де Persistent=true гарантує, що бекап станеться, навіть якщо машина спала в заплановану хвилину — чого cron просто не вміє.
— mrsaynothing
— mrsaynothing
Польові нотатки про ШІ, Linux і self-hosting.
Обговорити пост на dev.to dev.to ↗
Наступний гайд — на email
Один лист на пост. Полагодили — і далі.
що це таке?llama.cpp чи Ollama: що запускати у 2026 році?
Читається добре? Таке я будую за гроші. найміть мене