Timery systemd – przewodnik
Timery to wbudowany w systemd mechanizm harmonogramowania zadań.
Każdy timer to jednostka systemd z rozszerzeniem .timer
, która uruchamia powiązaną jednostkę .service
.
W praktyce każdy plik *.timer
musi wskazywać plik *.service
, opisujący co ma się wykonać.
Timery systemd oferują:
- harmonogramy kalendarzowe (OnCalendar) i monotoniczne (np. opóźnienia po starcie systemu)
- rejestrują zdarzenia w
journald
- pozwalają na definiowanie zależności między usługami
Jeśli server (lub PC) był wyłączony w czasie wywołania, timer po restarcie nadrobi wywołanie usługi (przy włączonym Persistent), co w cronie wymaga dodatkowych narzędzi (cronrun
/anacron
)
Porównanie z tradycyjnym cronem
Cron to klasyczny program do harmonogramowania zadań. Jest prosty w użyciu, ale ograniczony. Timery oferują większą elastyczność i integrację z systemem:
Zaawansowane opcje czasu
Timery systemd mogą działać kalendarzowo (podobnie jak cron) i monotonicznie - np. po zadanym czasie od uruchomienia systemu lub zakończenia innej usługi.
Dzięki temu można np. rozpocząć zadanie kilka minut po starcie systemu (OnBootSec=5min
) lub cyklicznie powtarzać zadanie co 6 godzin po jego zakończeniu (OnUnitActiveSec=6h
). Cron nie obsługuje takich zależności ani zdarzeń.
Rejestracja i monitorowanie
Każde wywołanie timera (i uruchamianej przez niego usługi) jest logowane w journald.
Można więc łatwo sprawdzić historię wywołań i błędów jednym poleceniem, np. journalctl -u custom.timer -u custom.service
.
W cronie wyniki trzeba zbierać samemu (np. przekierowując logi), a zadania różnych użytkowników są rozproszone w oddzielnych crontabach. Systemd pozwala z kolei wylistować wszystkie timery jednym poleceniem:
... uzyskujemy pełny podgląd zaplanowanych zadań (w przeciwieństwie do przeszukiwania wielu plików crontab).
Zarządzanie usługami
Timery są jednostkami systemd, więc można im przypisywać parametry kontroli zasobów, priorytety czy filtry systemcall. Może ono wymagać dołączenia zależności – np. uwierzytelnienia czy usługa B jest uruchomiona przed wykonaniem backupu.
W pliku usługi lub timera można zdefiniować Requires=
i After=
, gwarantując kolejność uruchomienia. Cron takiej kontroli nie oferuje.
Filtry systemcall w systemd (.service)
Filtry SystemCallFilter
w systemd ograniczają, co dany proces może wykonywać na poziomie jądra Linuksa. Pozwalają określić dozwolone lub zabronione wywołania systemowe (syscall), takie jak np. open()
, mount()
czy execve()
.
Dzięki temu możesz:
- chronić system przed błędami logicznymi lub lukami w aplikacjach,
- zabezpieczyć usługę przed potencjalnym złośliwym działaniem,
- ograniczyć wektor ataku (hardening),
- wymusić sandboxing dla procesów uruchamianych przez
systemd
.
Filtry te definiuje się w pliku .service
, np.:
Timer (.timer
) może uruchamiać usługę .service
, która posiada takie zabezpieczenia - dzięki temu zaplanowane zadania również działają w ograniczonym, kontrolowanym środowisku.
Bezpieczeństwo i uprawnienia
Dla zadań systemowych cron zwykle używa jednego kontekstu (np. root lub użytkownika), natomiast timery systemd mogą działać jako usługi systemowe lub usługę użytkownika (user-level). Można też łatwo ograniczyć prawo dostępu (np. za pomocą User=
w [Service]).
Charakterystyka cron'a
Cron jest prosty i dobrze znany, nie wymaga systemd, więc działa też na systemach bez niego.
Ma też prostszą konfigurację („jedna linia" zamiast dwóch plików).
Jest mniej elastyczny:
- Brak wsparcia dla zdarzeń (tylko stały harmonogram kalendarzowy)
- Brak łatwych mechanizmów monitorowania
- Brak mechanizmów przywracania zadań
- Brak kontroli zasobów
Note
Timery systemd to nowocześniejsza alternatywa dla crona, szczególnie gdy potrzebujemy lepszej kontroli, logowania i elastyczności. Dla prostych, rzadkich zadań nadal wystarczy cron, ale w wielu scenariuszach systemd jest wygodniejszy.
Tworzenie i konfiguracja timerów
Aby użyć timera, potrzebne są dwie jednostki: plik .service
(opisujący zadanie) i plik .timer
(opisujący harmonogram).
Jak utworzyć timer:
1. Plik usługi (.service
)
Definiuje polecenie do wykonania. Typowa struktura:
[Unit]
Description=Description
[Service]
ExecStart=/path/to/binary
Type=oneshot # (opcjonalnie, np. dla jednorazowego skryptu)
W ExecStart
używaj pełnych ścieżek oraz upewnij się, że program działa poprawnie
2. Plik timera (.timer
)
Określa, kiedy ma być uruchomiona powiązana usługa. Podstawowe sekcje:
[Unit]
Description=Task X timer
[Timer]
OnCalendar=... # warunek kalendarzowy (patrz niżej)
# lub:
OnBootSec=... # opóźnienie po starcie systemu
OnUnitActiveSec=... # opóźnienie po ostatnim uruchomieniu usługi
Persistent=true # (opcjonalnie: włącza "nadrobienie" przy starcie)
Unit=service_name # np. nazwa_pliku.service
[Install]
WantedBy=timers.target # aby timer włączał się przy starcie systemu
Plik timera musi mieć w [Timer]
ustawioną opcję Unit=
, wskazującą nazwę .service
.
Czas harmonogramu definiujemy przez OnCalendar (wyrażenie kalendarzowe) lub monotoniczne OnBootSec, OnUnitActiveSec itd.
Jak wyżej, możemy podać Persistent=true
, by systemd wykonał zadanie po restarcie, jeśli w czasie planowanego uruchomienia serwer (lub PC) był wyłączony.
3. Umiejscowienie plików
Pliki umieszczamy najczęściej w katalogu /etc/systemd/system/
(dla zadań systemowych dostępnych dla wszystkich użytkowników).
Mogą też trafiać do /usr/lib/systemd/system/
lub na poziom użytkownika (~/.config/systemd/user/
).
Po zapisaniu plików warto sprawdzić ich poprawność:
Jeżeli nie zwraca błędów, pliki są prawidłowe.
4. Uruchomienie timera
Po przygotowaniu plików należy załadować timer do systemd i uruchomić go:
systemctl daemon-reload # przeładowanie konfiguracji systemd (jeśli dodaliśmy pliki)
systemctl start custom.timer # uruchamia timer (nie rozpoczyna jeszcze usługi, ale wpisuje harmonogram)
systemctl enable custom.timer # włącza timer przy starcie systemu
Jak zwykle, dzięki enable
utworzy się odpowiedni link do timers.target
, zatem przy każdym uruchomieniu systemu timer będzie aktywowany automatycznie.
5. Przykład pełnej konfiguracji
Załóżmy skrypt /usr/local/bin/important.sh
, który chcemy uruchamiać 5 minut po starcie systemu, a potem co 24 godziny codziennie rano (pn-pt o 10:00). Pliki jednostek wyglądałyby tak:
# /etc/systemd/system/important.service
[Unit]
Description=Important service
[Service]
ExecStart=/usr/local/bin/important.sh
Type=oneshot
# /etc/systemd/system/important.timer
[Unit]
Description=Timer of Important service
[Timer]
OnBootSec=5min
OnUnitActiveSec=24h
OnCalendar=Mon..Fri *-*-* 10:00:00
Unit=important.service
Persistent=true
[Install]
WantedBy=timers.target
Pierwszy wywoła się ~5 min po uruchomieniu systemu, kolejne co 24 godziny o 10:00 w tygodniu. Dzięki Persistent=true
jeżeli komputer był wyłączony o planowanym czasie, timer uruchomi usługę po uruchomieniu systemu.
Pozostałe zastosowania
Praktycznie każde zadanie z crontaba można przenieść do timera systemd.
Dodatkową możliwością są timery użytkownika (w ~/.config/systemd/user/
), które uruchamiają zadania specyficzne dla danego konta bez potrzeby uprawnień roota.
Debugowanie i monitorowanie działania timerów
Systemd udostępnia narzędzia do sprawdzania stanu timerów:
Listowanie aktywnych timerów
wyświetla listę wszystkich timerów (wraz z kolumnami „NEXT" i „LAST" pokazującymi kolejne i ostatnie wywołanie), można sprawdzić, kiedy timer ma być następnie uruchomiony.
Status konkretnego timera lub usługi
pokażą bieżący stan (czy timer jest aktywny, kiedy ostatnio nastąpiło wywołanie, ewentualne błędy podczas uruchamiania skryptu).
Dziennik systemowy (journald)
Wszystkie zdarzenia timera i powiązanej usługi trafiają do journalctl
. Aby zobaczyć logi dla danego timera i usługi:
Można też użyć skrótu -u custom.*
dla obu jednocześnie. Przydatne flagi:
-b
(tylko bieżący start systemu)-S today
(od dziś)-x
(szczegółowe komunikaty)-f
(śledzenie w czasie rzeczywistym)
Warning
Jeśli coś nie działa, pierwszym krokiem jest zawsze sprawdzenie journalctl
pod kątem komunikatów o błędach.
Weryfikacja plików
Przed uruchomieniem warto sprawdzić składnię plików:
systemd-analyze verify /etc/systemd/system/custom.timer
systemd-analyze verify /etc/systemd/system/custom.service
Jeśli pojawią się błędy (np. literówki w nazwach opcji), narzędzie wyświetli odpowiednie ostrzeżenia. Przykładowo, literówka OnClendar
zamiast OnCalendar
jest zwykle ignorowana przez systemd, dlatego verify
pomaga takie pomyłki wychwycić.
systemd-analyze calendar
Do testowania wyrażeń kalendarzowych (OnCalendar
). Np.
pokaże dokładne czasy najbliższych uruchomień w czytelnej formie. To pomaga poprawnie skonfigurować złożone harmonogramy.
Najlepsze praktyki i pułapki
Kilka wskazówek do pracy z timerami:
Pełne ścieżki i środowisko
W plikach .service
zawsze podawaj pełną ścieżkę do skryptu lub programu. Domyślny PATH może być inny niż w cronie.
Jeśli skrypt używa zmiennych środowiskowych, ustaw je jawnie (np. Environment=VAR=value
lub w pliku .service
).
Tryb Type=oneshot
Jeśli usługa wykonuje tylko jednorazowe zadanie (wywołanie skryptu), warto użyć Type=oneshot
w [Service]
, co poprawnie obsłuży zakończenie działania.
Unit= i nazwa pliku
Upewnij się, że plik .timer
ma dokładnie zdefiniowane Unit=valid_custom.service
. Niepowiązanie timera z usługą to częsta przyczyna „nieaktywnego" timera.
WantedBy=timers.target
W sekcji [Install]
używaj WantedBy=timers.target
zamiast multi-user.target
. Dzięki temu timer zostanie poprawnie włączony podczas uruchamiania wszystkich timerów systemowych.
Sprawdzaj składnię
Nawet drobna literówka w nazwie opcji (OnCalendar
itp.) jest ignorowana bez błędu krytycznego. Zawsze użyj systemd-analyze verify
, by wychwycić takie literówki.
Monitoruj logi
Jeśli timer nie działa, sprawdź dziennik (journalctl
) i status. Często w logach znajdziesz informacje o przyczynach błędów (np. uprawnienia, brak pliku, itp.).
Używaj timerów per user (jeśli potrzebne)
Systemd pozwala na timery na poziomie użytkownika (uruchamiane z systemctl --user
). Przydatne do zadań nie wymagających roota, np. synchronizacja plików w Home.
Podsumowanie
Timery systemd są kompleksowe, ale wymagają dyscypliny konfiguracji.
Istotne jest poprawne zdefiniowanie plików .service
i .timer
, używanie narzędzi weryfikujących (systemd-analyze
, status
, journalctl
) oraz zrozumienie, które opcje odpowiadają za harmonogram.