Modul 6 · 6.3
Saját szolgáltatások és időzítők
Modul 6: Szolgáltatások és naplók · Olvasási idő: 11 perc
Tanulási cél: A lecke után Ön képes lesz egy saját programot systemd-szolgáltatásként futtatni egy külön felhasználó alatt, néhány biztonsági opcióval, és feladatokat ütemezni systemd-időzítővel vagy cronnal.
Kulcsfogalmak: unit-fájl, [Unit], [Service], [Install], ExecStart, User=, WorkingDirectory, EnvironmentFile, Restart=, WantedBy, NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp, systemd-analyze security, időzítő (timer), OnCalendar, Persistent, crontab
Miért ne egyszerűen "nohup" vagy "screen"?
Aki saját programot telepít egy szerverre (egy kis webalkalmazást, egy botot, egy szkriptet, amely minden éjjel elvégez valamit), az első alkalommal gyakran kézzel indítja el: node server.js &, vagy egy screen-munkamenetben. Ez addig működik, amíg ki nem jelentkezik, a szerver újra nem indul, vagy a program össze nem omlik. Ekkor eltűnik, és senki sem veszi észre.
Egy programnak, amelynek folyamatosan futnia kell, systemd-szolgáltatásnak kell lennie. Ekkor:
- magától elindul a rendszerindításkor;
- a systemd újraindítja, ha összeomlik;
- a kimenete a journalba kerül (6.2. lecke);
- az Ön által választott felhasználó alatt fut, azokkal a jogosultságokkal, amelyeket Ön megenged.
Saját unit-fájl
Tegyük fel, hogy van egy kis Node.js-alkalmazása a /opt/factuurapp mappában, amely a 127.0.0.1:3000 címen figyel. Később az nginx vagy a Caddy teszi elérhetővé kívülről (7. modul).
1. lépés: saját felhasználó shell nélkül (3.2. lecke). Az alkalmazásnak nem kell rootként futnia, és bejelentkeznie sem kell:
anna@web1:~$ sudo adduser --system --group --home /opt/factuurapp --no-create-home factuurapp
anna@web1:~$ sudo chown -R factuurapp:factuurapp /opt/factuurapp/dataMaga a kód maradhat a root tulajdonában (az alkalmazásnak nem kell önmagát módosítania); csak az a mappa tartozik a szolgáltatás felhasználójához, amelybe ír.
2. lépés: a unit-fájl. A saját unitokat a /etc/systemd/system/ mappába helyezze:
# /etc/systemd/system/factuurapp.service
[Unit]
Description=Factuurapp (Node.js)
After=network-online.target
Wants=network-online.target
[Service]
User=factuurapp
Group=factuurapp
WorkingDirectory=/opt/factuurapp
EnvironmentFile=/etc/factuurapp/env
ExecStart=/usr/bin/node /opt/factuurapp/server.js
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/opt/factuurapp/data
[Install]
WantedBy=multi-user.targetA három blokk:
- [Unit]: leírás és sorrend. A
After=network-online.targetaWants=beállítással együtt biztosítja, hogy a szolgáltatás csak akkor induljon el, amikor a hálózat már elérhető. - [Service]: hogyan fut a program.
ExecStarta teljes elérési úttal (a systemd nem használ keresési útvonalat, mint az Ön shellje). AUser=és aGroup=határozza meg, ki alatt fut. AzEnvironmentFileegy külön fájlból olvassa be a beállításokat, például egy adatbázisjelszót, így azok nem a unitban szerepelnek. - [Install]: mit csinál a
enable. AWantedBy=multi-user.targetjelentése: induljon el egy normál rendszerindításkor.
3. lépés: a titkok külön, szigorú jogosultságokkal.
anna@web1:~$ sudo mkdir /etc/factuurapp
anna@web1:~$ sudo install -m 600 -o root -g root /dev/null /etc/factuurapp/env
anna@web1:~$ sudoedit /etc/factuurapp/envA tartalom például DATABASE_URL=postgres://factuur:...@127.0.0.1/factuur. A systemd rootként olvassa be a fájlt, mielőtt átvált a szolgáltatás felhasználójára, ezért elegendő a root tulajdonában lévő 600.
4. lépés: betöltés, indítás, ellenőrzés.
anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl enable --now factuurapp
anna@web1:~$ systemctl status factuurapp
anna@web1:~$ journalctl -u factuurapp -fBiztonsági opciók: kis ráfordítás, nagy különbség
A példában a RestartSec alatti négy sor korlátozza, mire képes a szolgáltatás, akkor is, ha valaki biztonsági rést talál az alkalmazásában:
| Opció | Hatás |
|---|---|
NoNewPrivileges=true | a folyamat és gyermekfolyamatai soha nem kaphatnak több jogosultságot (a sudo vagy setuid-programok révén sem) |
ProtectSystem=strict | a teljes fájlrendszer csak olvasható a szolgáltatás számára, kivéve azt, amit a ReadWritePaths= segítségével engedélyez |
ProtectHome=true | a /home, a /root és a /run/user láthatatlan |
PrivateTmp=true | saját, üres /tmp, amelyet más programok nem látnak |
A systemd értékelni tudja a unitot:
anna@web1:~$ systemd-analyze security factuurapp
...
→ Overall exposure level for factuurapp.service: 4.9 OK 🙂Minél alacsonyabb a szám, annál jobb. Egy opciók nélküli szolgáltatás 9 körüli pontszámot kap ("UNSAFE"). Nem kell nulláig eljutnia: minden hozzáadott opció elronthat valamit, amire az alkalmazásnak szüksége van. Egyenként adja hozzá őket, és minden lépés után teszteljen. Ha valami már nem működik, az többnyire látszik a journalban ("Read-only file system", "Permission denied").
Feladatok ütemezése: időzítők
Ahhoz, aminek meghatározott időpontokban kell megtörténnie (biztonsági mentés, takarítószkript, jelentés), időzítőre (timer) van szükség. Egy systemd-időzítő két azonos nevű unitból áll: egy .service fájlból, amely megmondja, mi történjen, és egy .timer fájlból, amely megmondja, mikor.
# /etc/systemd/system/opruimen.service
[Unit]
Description=Oude exportbestanden opruimen
[Service]
Type=oneshot
User=factuurapp
ExecStart=/usr/bin/find /opt/factuurapp/data/export -type f -mtime +30 -delete# /etc/systemd/system/opruimen.timer
[Unit]
Description=Dagelijks oude exportbestanden opruimen
[Timer]
OnCalendar=*-*-* 03:15:00
RandomizedDelaySec=10m
Persistent=true
[Install]
WantedBy=timers.targetA Type=oneshot jelentése: a program lefut, majd befejeződik. Az OnCalendar az ütemezés: minden nap 03:15-kor. Írhat daily, weekly vagy Mon *-*-* 02:00 értéket is; a systemd-analyze calendar "Mon *-*-* 02:00" megmutatja, mikor lesz a következő futás. A Persistent=true fontos: ha a szerver 03:15-kor ki volt kapcsolva, a feladat a rendszerindítás után azonnal pótlólag lefut. A RandomizedDelaySec kissé szétszórja az indítás időpontját.
A bekapcsolást az időzítővel végezze, ne a service-szel:
anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl enable --now opruimen.timer
anna@web1:~$ systemctl list-timers opruimen
NEXT LEFT LAST PASSED UNIT ACTIVATES
Tue 2026-11-10 03:19:42 CET 15h left - - opruimen.timer opruimen.service
anna@web1:~$ sudo systemctl start opruimen.service # most egyszeri kézi tesztelés
anna@web1:~$ journalctl -u opruimen.serviceÉs a cron?
A cron a régebbi, egyszerűbb eszköz, és továbbra is jól működik. Egy sor egy felhasználó crontabjában (crontab -e):
15 3 * * * /usr/local/bin/opruimen.shAz öt mező: perc, óra, a hónap napja, hónap és a hét napja. Az előnyök és hátrányok egymás mellett:
| cron | systemd-időzítő | |
|---|---|---|
| Beállítás | egy sor | két fájl |
| Kimaradt futás (a szerver ki volt kapcsolva) | kimarad | a Persistent=true segítségével pótlólag lefut |
| Kimenet és hibák | e-mailben, ha a szerver tud levelet küldeni; különben elvesznek | a journalban |
| Biztonsági opciók, felhasználó | magán a szkripten keresztül | a systemd összes lehetősége (lásd fent ebben a leckében) |
| Annak megtekintése, mikor futott | nehézkes | systemctl list-timers és a journal |
Egy komolyan üzemeltetett szerveren az időzítők a jobb választás, különösen a biztonsági mentésekhez (8.2. lecke): biztosan tudni szeretné, hogy lefutottak, és mit írtak ki. Egy csendben hibázó cronsort csak akkor vesz észre, amikor szüksége lenne a mentésre.
AlmaLinux és Rocky Linux rendszeren
A unitok és az időzítők pontosan ugyanígy működnek. Egy különbség: a SELinux megakadályozhatja egy saját szolgáltatás működését, ha az olyan helyen olvas vagy ír fájlokat, amelyre a SELinux nem számít, vagy szokatlan porton figyel. Az üzenet a /var/log/audit/audit.log fájlban található. Ne kapcsolja ki a SELinuxot a probléma megoldásához; keresse meg a megfelelő címkét vagy szabályt (például a semanage segítségével).
Összefoglalás
- Egy programnak, amelynek folyamatosan futnia kell, systemd-szolgáltatásnak kell lennie: magától elindul, összeomláskor újraindul, a naplók a journalba kerülnek.
- A saját unitok helye a
/etc/systemd/system/, aUser=segítségével egy saját, shell nélküli felhasználóval, a titkok pedig egy 600-as jogosultságúEnvironmentFilefájlban. - A
NoNewPrivileges, aProtectSystem=strictaReadWritePathsbeállítással, aProtectHomeés aPrivateTmpkorlátozza a kárt egy biztonsági rés esetén; asystemd-analyze securityértékeli a unitot. - Egy időzítő egy
.serviceés egy.timerazOnCalendarbeállítással; aPersistent=truepótolja a kimaradt futásokat. Az időzítőt kapcsolja be, ne a service-t. - A cron továbbra is működik, de az időzítők jobb naplókat adnak, és nem hagynak ki futásokat.
Kvíz
Feladat
O6.3. feladat: Saját szolgáltatás időzítővel. Hozzon létre a szerverén egy kis saját szolgáltatást időzítővel, például egy szkriptet, amely minden éjjel egy fájlba vagy a journalba írja a szabad lemezterületet és a systemctl --failed kimenetét. Használjon saját felhasználót, Type=oneshot beállítást, legalább két biztonsági opciót és Persistent=true beállítást. Teszteljen a systemctl start paranccsal, nézze meg a kimenetet a journalban, és jegyezze fel a systemd-analyze security pontszámát. Illessze be a .service és a .timer fájlt, és válaszoljon az ellenőrzőlista kérdéseire.
O6.3. feladat: Saját szolgáltatás időzítővel
Ezt a feladatot saját maga végzi el, senki nem ellenőrzi. Pipálja ki, amit elvégzett, és jelölje meg a feladatot elvégzettként.
A Persistent=true beállítással a feladat indítás után utólag lefut. Egy első szolgáltatásnál a 6 alatti pontszám jó; írási jog csak a ReadWritePaths révén.
A pipái és jegyzetei csak ebben a böngészőben maradnak meg, sehova nem küldjük el őket. Ha bejelentkezett, a Fiókomban csak azt tároljuk, hogy elvégezte a feladatot.
További olvasnivaló
- DirectAdmin útmutató 15.1: Időzített feladatok: feladatok automatikus futtatása
- A
systemd.exec(5)kézikönyve (User=, ProtectSystem=, NoNewPrivileges=): https://manpages.debian.org/trixie/systemd/systemd.exec.5.en.html - A
systemd.timer(5)kézikönyve (OnCalendar=, Persistent=): https://manpages.debian.org/trixie/systemd/systemd.timer.5.en.html - A
systemd.time(7)kézikönyve (ütemezések): https://manpages.debian.org/trixie/systemd/systemd.time.7.en.html
