SystemD időzítő alapok

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>

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

......

> 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. 

A szokott helyen, a magyarlinux.hu-n jelent meg...