Systemd időzítő alapok

systemd időzítő
Sudo beállítása

A systemd időzítő használata első látásra sokkal bonyolultabbnak tűnik, mint a cron. Ez valóban így is van, de a több lehetőség miatt legalább egy próbát megér a dolog.
Ha az előző részekben leírt módszerrel kilistáztad a systemd részeit, az aktívan futó eszközöket, akkor láthattad, hogy van olyan, hogy .timers. Ezek az időzítő rendszer részei. Itt is, mint a legtöbb esetben csak az alapokat beszéljük meg, inkább kedvcsinálónak, mint komoly és alapos leírásnak szánom a systemd időzítő témát. A példa nagyon egyszerű lesz, mert csak egy alap parancsot indítunk el, majd annak a kimenetét nézzük meg. Ennek analógiájára már bármely szkriptet, parancsot tudunk időzíteni.

A systemd időzítő a free parancshoz

Alap feladat: futtassunk egy free parancsot percenként. Ezt a cron is megtehetné, de most a systemd időzítőjével oldjuk meg.

Két fájl kell, az egyik egy sima „service” fájl, ami megmondja, hogy mi a feladat és pár adminisztratív dolgot megtesz nekünk. A másik az időzítő rész.

Első lépés, hogy belépünk a /etc/systemd/system könyvárba. Ez fontos, mert nem egy szkriptet írunk, aminek megadhatjuk az elérési útját induláskor, hanem egy szervizt használunk, aminek a helye kötött. Már most látjuk, hogy itt csak rendszergazdaként tudunk dolgozni, így ha valami nem megy, akkor a sudo hiányára gyanakodjunk. Egyszerűbb a a sudo, minthogy minden lépésnél bekérje a jelszavunkat! Én sehova nem írom ki a sudo-t, így aki csak másolgat, annak oda kell elé tenni.

A következő lépés már a lehető legegyszerűbb service fájl elkészítése.

nano myMonitor.service

Azaz elkezdjük a szerkesztést. Én az eredeti cikk (opensource.com) példáját másolom be ide.

# This service unit is for testing timer units
# By David Both
# Licensed under GPL V2
#

[Unit]
Description=Logs system statistics to the systemd journal
Wants=myMonitor.timer

[Service]
Type=oneshot
ExecStart=/usr/bin/free

[Install]
WantedBy=multi-user.target

Majd mentjük, és a szerkesztőből kilépünk. Majd rákérdezünk, hogy valóban van-e ilyen service. A sokadik systemd fájl szerkesztése után már nem kell, de az elején jobb, ha valóban meggyőződsz róla, hogy nem írtál el valamit és nincs vele gond.

systemctl status myMonitor.service

laci:system/ $ systemctl status myMonitor.service [7:02:06]
● myMonitor.service – Logs system statistics to the systemd journal
Loaded: loaded (/etc/systemd/system/myMonitor.service; disabled; vendor preset: disabled)
Active: inactive (dead)

Ha rendesen megjelenik, akkor nincs probléma. Majd el kell indítani.

systemctl start myMonitor.service

Ezután már fut egy szervizünk, ami egyszer kiírja a free értékét. Hm… nem láttál semmit? Annak egy az oka: a logba fogja írni alapesetben az eredményt, így nézzük is meg a logot:

journalctl -S today -f -u myMonitor

nov 12 07:03:58 laci systemd[1]: Starting Logs system statistics to the systemd journal…
nov 12 07:03:58 laci free[5559]: total used free shared buff/cache available
nov 12 07:03:58 laci free[5559]: Mem: 16376504 3645944 9728204 218952 3002356 12214496
nov 12 07:03:58 laci free[5559]: Swap: 4194300 0 4194300
nov 12 07:03:58 laci systemd[1]: myMonitor.service: Succeeded.
nov 12 07:03:58 laci systemd[1]: Finished Logs system statistics to the systemd journal.

Szuper, ez működik. Állítsd is le, mert ne fusson valami hiába, hiszen egy alkalommal lefut és azután már nem. Pont az a célunk, hogy egyfajta megoldással oldjuk meg a periodikus futtatást, és írja bele a logba a free adatokat.

Miután kiderült, hogy a service rendesen lefut, már csak a systemd időzítő szolgáltatást kell megoldani.

Systemd időíztő beállítása

A /etc/systemd/system könyvtárban az myMonitor.timer fájlt kell létrehozni ezzel a tartalommal:

# This timer unit is for testing
# By David Both
# Licensed under GPL V2
#

[Unit]
Description=Logs some system statistics to the systemd journal
Requires=myMonitor.service

[Timer]
Unit=myMonitor.service
OnCalendar=*-*-* *:*:00

[Install]
WantedBy=timers.target

Lemented. A OnCalendar idő specifikáció *-*-* *:*:00, azaz a myMonitor.service fusson percenként. A OnCalendar beállításokat egy kicsit később részletezem, bár a leírások nagyon jók.

systemctl start myMonitor.service

Elindítjuk a szolgáltatást. Majd várunk pár percet, hogy legyen legalább pár érdemi lefutása.

Nézzük meg, hogy mit is ad kimenetnek a logban.

journalctl -S today -f -u myMonitor

nov 12 08:18:39 laci systemd[1]: Starting Logs system statistics to the systemd journal…
nov 12 08:18:39 laci free[14286]: total used free shared buff/cache available
nov 12 08:18:39 laci free[14286]: Mem: 16376504 3356536 7210120 163756 5809848 12541016
nov 12 08:18:39 laci free[14286]: Swap: 4194300 0 4194300
nov 12 08:18:39 laci systemd[1]: myMonitor.service: Succeeded.
nov 12 08:18:39 laci systemd[1]: Finished Logs system statistics to the systemd journal.
nov 12 08:19:05 laci systemd[1]: Starting Logs system statistics to the systemd journal…
nov 12 08:19:05 laci free[14422]: total used free shared buff/cache available
nov 12 08:19:05 laci free[14422]: Mem: 16376504 3426908 7130056 164448 5819540 12469908
nov 12 08:19:05 laci free[14422]: Swap: 4194300 0 4194300
nov 12 08:19:05 laci systemd[1]: myMonitor.service: Succeeded.
nov 12 08:19:05 laci systemd[1]: Finished Logs system statistics to the systemd journal.
nov 12 08:20:08 laci systemd[1]: Starting Logs system statistics to the systemd journal…
nov 12 08:20:08 laci free[14553]: total used free shared buff/cache available
nov 12 08:20:08 laci free[14553]: Mem: 16376504 3780980 6702768 208672 5892756 12071360
nov 12 08:20:08 laci free[14553]: Swap: 4194300 0 4194300
nov 12 08:20:08 laci systemd[1]: myMonitor.service: Succeeded.
nov 12 08:20:08 laci systemd[1]: Finished Logs system statistics to the systemd journal.

A lehető legegyszerűbb timer, azaz időzítő systemd megoldás felépítése egyszerű:

# Nem is kell magyarázni,
# a megjegyzések helye.

[Unit]
Description=Magyarázat, ami megjeleníthető. Ne hagyd el!
Requires=myMonitor.service azaz az indítandó szerviz neve, amire szükség van.

[Timer]
Unit=myMonitor.service azaz az indítandó szerviz neve, pontosan.
OnCalendar=*-*-* *:*:00 a ritmus, az időzítés megadása.

[Install]
WantedBy=timers.target

Ahhoz, hogy az időzítő automatikusan elinduljon indításkor, mindössze annyit kell tennünk, hogy megbizonyosodjunk arról, hogy van-e benne [Install] szakasz, ahol megadjuk, hogy mikor történjen az aktiválás. A fenti példában a WantedBy kulcsszót arra használjuk, hogy megállapítsuk egy adott célegységet. A timers.target a rendszer indítási folyamat elég korai szakaszában induló bejegyzés, ezzel meghatározzuk, hogy aktív legyen a rendszerindulás után – ha azt az enable kapcsolóval véglegesíted. A start/stop kapcsoló egyszeri alkalomra szól, reboot után már nem érvényes indítást/leállítást ad. Volt róla szó!

Arra mindig ügyelj, hogy minden esetben előbb a service-t próbáld ki, majd azután az időzítő systemd szolgáltatást. Bár egyszerű, illetve a példa egyszerű, de ha elírsz valamit, bosszantó lehet utólag keresni a hibát.

A naplóban látni?

Valószínűleg legalább két dolgot észrevettél a naplóban. Először is, nem kell semmit tenni ahhoz, hogy napló a ExecStart után megadott program kimenete bekerüljön a naplóba.. Ez mind része a systemd szolgáltatásainak. Gyakorlatilag a rendszer dolgait, azokat a szolgáltatásokat állítja be, amik fontosak, így a naplózás nem maradhat el. Ez azonban azt jelenti, hogy óvatosnak kell lenni a szkriptek futtatásával, mert a sok és sokszor lefutás már teletömheti a naplódat és ha annak mérete kicsire van állíva, akkor lehet, hogy régebbi, de fontos naplózás törlésre kerül. Bár itt egy semleges, igazából nem használható időzítésre adtunk megoldást, de a napló pld. a rendszer frissítésre írt szkript, vagy egyéb fontos feladatnál már lényegesebb.

A második dolog is fontos, bár az esetek legnagyobb részében lényegtelen. Az időzítő nem pontosan egész percben, a 00 másodpercnél fut le.Ez szándékos, de szükség esetén felülbírálható.

Ennek a viselkedésnek az az oka, hogy megakadályozza, hogy több szolgáltatás egyszerre induljon el. Használhatunk például az olyan időspecifikációkat, mint a heti, napi stb. Ezek a parancsok úgy vannak meghatározva, hogy a kiváltás napján 00:00:00 órakor aktiválódjanak. Ha több időzítőt adunk meg így, akkor nagy a valószínűsége annak, hogy megpróbálnának egyszerre elindulni. Ami leterhelheti a rendszert. Bár van megoldás a pontosabb teljesülésre, de aminél nem lényeges a perces, vagy a jelen esetben a másodperces pontosság hagyjuk a rendszerre a beosztást.
Ha pedig a pontosságra nagyon kell figyelni, akkor a AccuracySec= sort beillesztve a
usec, us, µs
msec, ms
seconds, second, sec, s
minutes, minute, min, m
hours, hour, hr, h

értelemszerű megadásával kényszeríthetjük a systemd időzítő rendszerét a pontosabb munkára. Ha kíváncsi vagy melyik timer szolgáltatás milyen pontosságot vár el. Akkor a grep Accur

/usr/lib/systemd/system/*timer

megkaphatod. Láthatod, hogy nem feltétlen kell a nanosecundum tört része 🙂

A ciklikus időzítő beállításai a systemd rendszerben

A legegyszerűbb beállítás módja nagyban hasonló a cron-hoz.

ÉÉÉÉ-HH-NN ÓÓ: HH: SS

Figyelj a – és a : jelekre, itt fontosak. A * – * – * 00:15:30 minden év minden hónapjának minden napján 15 perc és 30 másodperc éjfél után. Logikus. Ezenkívül rengeteg beállítási, egyszerűsítési lehetőséged van. Ha az időpont nincs megadva, akkor azt 00:00:00 -nak kell tekinteni. Ha a dátum nincs megadva, de az idő megvan, a következő futás ma vagy holnap lehet, az aktuális időtől függően. Nevek vagy számok használhatók a hónapra és a hét napjára. Angolul!

Az egyes egységek vesszővel elválasztott listák megadhatók, felsorolhatóak.

Az egységtartományok megadhatók .. a kezdő és a befejező érték között. Van néhány érdekes lehetőség a dátumok megadására. A tilde (~) segítségével megadható a hónap utolsó napja vagy a hónap utolsó napját megelőző meghatározott napok száma. A „/” karakterrel módosítóként megadható a hét napja. Bár a lehetőségek igencsak zavarba ejtőek, de nem kell az összes variációt használni, csak az előbb bemutatott megoldás ismerete elegendő. Ha pedig kedveled az extra lehetőségeket a systemd.timer man oldala segít. Ott is van pár példa, de ide is beteszek párat.

*: 0/2 A feladatot két percenként hajtják végre a 0 perctől kezdve
15/2 A feladatot 15:00 órától két óránként hajtják végre
Weekly Minden hétfőn 00:00:00 órakor
Mon *-*-* 00:00:00 Ugyanaz, mint az előbbi
Mon Ugyanaz, mint hetente
Wed 2020-*-* 2020-ban minden szerdán 00:00:00 órakor
Mon..Fri 2021-*-* 2021-ben minden hétköznap 00:00:00 órakor
2022-6,7,8-1,15 01:15:00 2022. június, július és augusztus 1-jén, 15-én 01: 15: 00-kor
Mon *-05~03 Bármely év májusának hétfőjének következő előfordulása, amely a hónap végétől számított 3. nap.
Mon..Fri *-08~04 Az augusztus végét megelőző 4. nap minden olyan évre, amelyben szintén hétköznapra esik.
*-05~03/2 Május végétől a 3. nap, majd két nappal később. Minden évben megismétlődik. Vedd figyelembe, hogy ez a kifejezés a tilde (~) jelet használja.
*-05-03/2 Május harmadik napja, majd május hátralévő részében minden 2. nap. Minden évben megismétlődik. Vedd figyelembe, hogy ez a kifejezés a kötőjelet (-) használja.

A végén lévők nem biztos, hogy élő példák, mert nagyon kétséges, hogy ezeket az életben használni fogod.

Az idők tesztelése

A systemd készítői nagyon jól ráéreztek, hogy sokaknak a cron viszonylag egyszerű beállítása is gondot okoz, így lehetőséget adtak a tesztelésre is.

systemd-analyze calendar 2022-06-17

Original form: 2022-06-17
Normalized form: 2022-06-17 00:00:00 a pontos megadási mód
Next elapse: Fri 2022-06-17 00:00:00 CEST a következő lefutás közép európai idő szerint
(in UTC): Thu 2022-06-16 22:00:00 UTC UTC idő szerint
From now: 1 years 7 months left ennyi idő van hátra még

Futtasd ezt is le, és tanulmányozd az eltéréseket

systemd-analyze calendar 2022-0-17 11:01:16
systemd-analyze calendar „2022-0-17 11:01:16”

De megadhatsz komolyabbat is:

systemd-analyze calendar "2022-6,7,8-1,15 01:15:00" vagy ha nem csak a következő, hanem a következő öt lefutást szeretnéd látni:

systemd-analyze calendar --iterations=5 "Mon *-05~3"

Így tesztelheted a beállításaid helyességét.

Bár sok esetben az időpontok megadás jó megoldás, de van pár olyan kapcsoló is, ami relatív időt ad meg.
OnActiveSec Ütemezze a feladatot ahhoz az időponthoz képest, amikor maga az időzítő egység aktiválódik
OnBootSec Ütemezze a feladatot a rendszer indítási idejéhez viszonyítva
OnStartupSec Ütemezze a feladatot ahhoz a ponthoz képest, amikor a Systemd elindult
OnUnitActiveSec Ütemezze a feladatot ahhoz képest, amikor a szervizegység legutóbb aktív volt
OnUnitInactiveSec Ütemezze a feladatot ahhoz képest, amikor a szolgáltató egység utoljára inaktív volt

Egy fontos lekérdezés

systemctl list-timers

A kimenet egyértelmű:
NEXT LEFT LAST PASSED UNIT ACTI>
Thu 2020-11-12 10:48:00 CET 16s left Thu 2020-11-12 10:47:08 CET 35s ago myMonitor.timer myMo>
Fri 2020-11-13 00:00:00 CET 13h left Thu 2020-11-12 00:00:01 CET 10h ago man-db.timer man->
Fri 2020-11-13 00:00:00 CET 13h left Thu 2020-11-12 00:00:01 CET 10h ago shadow.timer shad>
Fri 2020-11-13 00:00:00 CET 13h left Thu 2020-11-12 00:00:01 CET 10h ago updatedb.timer upda>
Fri 2020-11-13 06:28:19 CET 19h left Thu 2020-11-12 06:28:19 CET 4h 19min ago systemd-tmpfiles-clean.timer syst>
Sat 2020-12-05 15:00:00 CET 3 weeks 2 days left Sat 2020-11-07 15:00:01 CET 4 days ago pamac-cleancache.timer pama>

6 timers listed.

Összefoglalva: a systemd időzítő lehetőse adott, viszonylag egyszerű is. Előbb egy .service fájlt készítünk, majd ahhoz egy timer-t. A legtöbb esetben elegendő az egyszerűbb formában megadni a periódust, de van lehetőséged ezt pontosítani, illetve egyéb, relatív (Monotonic) meghatározásra is.

Related Posts