Vlastní služby a časovače
Modul 6: Služby a logy · Doba čtení: 11 min.
Cíl lekce: Po této lekci dokážete spustit vlastní program jako službu systemd pod vlastním uživatelem a s několika bezpečnostními volbami a naplánovat úlohy pomocí časovače systemd nebo cronu.
Klíčové pojmy: soubor unit, [Unit], [Service], [Install], ExecStart, User=, WorkingDirectory, EnvironmentFile, Restart=, WantedBy, NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp, systemd-analyze security, časovač (timer), OnCalendar, Persistent, crontab
Proč ne jednoduše "nohup" nebo "screen"?
Kdo umístí na server vlastní program (malou webovou aplikaci, bota, skript, který každou noc něco provede), spouští ho poprvé často ručně: node server.js &, nebo v relaci screen. Funguje to, dokud se neodhlásíte, server se nerestartuje nebo program nespadne. Pak je pryč a nikdo si toho nevšimne.
Program, který musí běžet neustále, má být službou systemd. Potom:
- se spustí sám při startu systému;
- systemd ho znovu spustí, když spadne;
- jeho výstup se ukládá do journalu (lekce 6.2);
- běží pod uživatelem, kterého zvolíte, s oprávněními, která povolíte.
Vlastní soubor unit
Představte si, že máte malou aplikaci v Node.js v /opt/factuurapp, která naslouchá na 127.0.0.1:3000. Navenek ji později zpřístupní nginx nebo Caddy (modul 7).
Krok 1: vlastní uživatel bez shellu (lekce 3.2). Aplikace nemusí běžet jako root a nemusí se přihlašovat:
anna@web1:~$ sudo adduser --system --group --home /opt/factuurapp --no-create-home factuurapp
anna@web1:~$ sudo chown -R factuurapp:factuurapp /opt/factuurapp/dataSamotný kód může dál patřit uživateli root (aplikace nemusí měnit sama sebe); uživateli služby patří jen adresář, do kterého zapisuje.
Krok 2: soubor unit. Vlastní unity ukládáte do /etc/systemd/system/:
# /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.targetTři bloky:
- [Unit]: popis a pořadí.
After=network-online.targetspolu sWants=zajistí, že se služba spustí až ve chvíli, kdy je k dispozici síť. - [Service]: jak program běží.
ExecStarts úplnou cestou (systemd nepoužívá vyhledávací cestu jako Váš shell).User=aGroup=určují, pod kým program běží.EnvironmentFilenačte nastavení, například heslo k databázi, ze samostatného souboru, takže nejsou uvedena přímo v unitu. - [Install]: co provede
enable.WantedBy=multi-user.targetznamená: spustit spolu s běžným startem systému.
Krok 3: tajné údaje zvlášť, s přísnými oprávněními.
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/envObsah může být například DATABASE_URL=postgres://factuur:...@127.0.0.1/factuur. systemd soubor přečte jako root dřív, než se přepne na uživatele služby, takže 600 s vlastníkem root stačí.
Krok 4: načíst, spustit, zkontrolovat.
anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl enable --now factuurapp
anna@web1:~$ systemctl status factuurapp
anna@web1:~$ journalctl -u factuurapp -fBezpečnostní volby: malá námaha, velký rozdíl
Čtyři řádky pod RestartSec v příkladu omezují, co služba smí dělat, i když někdo ve Vaší aplikaci najde zranitelnost:
| Volba | Účinek |
|---|---|
NoNewPrivileges=true | proces a jeho potomci nikdy nemohou získat vyšší oprávnění (ani přes sudo nebo programy se setuid) |
ProtectSystem=strict | celý souborový systém je pro službu jen pro čtení, kromě toho, co povolíte pomocí ReadWritePaths= |
ProtectHome=true | /home, /root a /run/user jsou neviditelné |
PrivateTmp=true | vlastní prázdný /tmp, který ostatní programy nevidí |
systemd umí Váš unit ohodnotit:
anna@web1:~$ systemd-analyze security factuurapp
...
→ Overall exposure level for factuurapp.service: 4.9 OK 🙂Čím nižší číslo, tím lépe. Služba bez voleb má skóre kolem 9 ("UNSAFE"). Na nulu se dostat nemusíte: každá přidaná volba může rozbít něco, co aplikace potřebuje. Přidávejte je jednu po druhé a po každém kroku testujte. Pokud něco přestane fungovat, většinou to najdete v journalu ("Read-only file system", tedy souborový systém jen pro čtení, nebo "Permission denied", tedy přístup odepřen).
Plánování úloh: časovače
Pro něco, co se má dít v pevně daných časech (záloha, úklidový skript, report), potřebujete časovač (timer). Časovač systemd se skládá ze dvou unitů se stejným názvem: .service, který říká, co se má stát, a .timer, který říká kdy.
# /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.targetType=oneshot znamená: program se spustí a potom skončí. OnCalendar je časový plán: každý den v 03:15. Můžete také napsat daily, weekly nebo Mon *-*-* 02:00; systemd-analyze calendar "Mon *-*-* 02:00" ukáže, kdy to bude příště. Persistent=true je důležité: pokud byl server v 03:15 vypnutý, úloha se spustí dodatečně hned po startu. RandomizedDelaySec okamžik spuštění trochu rozprostře.
Zapínáte časovač, ne službu:
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 # nyní jednou otestovat ručně
anna@web1:~$ journalctl -u opruimen.serviceA co cron?
cron je starší a jednodušší nástroj a stále funguje dobře. Řádek v crontabu uživatele (crontab -e):
15 3 * * * /usr/local/bin/opruimen.shPět polí znamená minutu, hodinu, den v měsíci, měsíc a den v týdnu. Výhody a nevýhody vedle sebe:
| cron | časovač systemd | |
|---|---|---|
| Nastavení | jeden řádek | dva soubory |
| Zmeškané spuštění (server vypnutý) | přeskočí se | s Persistent=true proběhne dodatečně |
| Výstup a chyby | e-mailem, pokud server umí odesílat poštu; jinak se ztratí | v journalu |
| Bezpečnostní volby, uživatel | přes samotný skript | vše ze systemd (viz výše v této lekci) |
| Zjistit, kdy běžel | obtížné | systemctl list-timers a journal |
Pro server, který spravujete vážně, jsou časovače lepší volbou, hlavně u záloh (lekce 8.2): chcete mít jistotu, že proběhly a co hlásily. Řádek v cronu, který potichu selže, odhalíte až ve chvíli, kdy zálohu potřebujete.
Na AlmaLinux a Rocky Linux
Unity a časovače fungují úplně stejně. Jeden rozdíl: SELinux může zablokovat vlastní službu, která čte nebo zapisuje soubory na místě, které SELinux neočekává, nebo která naslouchá na neobvyklém portu. Hlášení najdete v /var/log/audit/audit.log. Nevypínejte kvůli tomu SELinux; najděte správný label nebo pravidlo (například pomocí semanage).
Shrnutí
- Program, který musí běžet neustále, má být službou systemd: sám se spustí, po pádu se restartuje a logy jdou do journalu.
- Vlastní unity patří do
/etc/systemd/system/, sUser=jako vlastním uživatelem bez shellu a tajnými údaji vEnvironmentFiles oprávněními 600. NoNewPrivileges,ProtectSystem=strictsReadWritePaths,ProtectHomeaPrivateTmpomezují škody při zneužití zranitelnosti;systemd-analyze securityunit ohodnotí.- Časovač je
.serviceplus.timersOnCalendar;Persistent=truedožene zmeškaná spuštění. Zapínejte časovač, ne službu. - cron stále funguje, ale časovače poskytují lepší logy a nevynechají žádné spuštění.
Kvíz
Úkol
Úkol O6.3: Vlastní služba s časovačem. Vytvořte na svém serveru malou vlastní službu s časovačem, například skript, který každou noc zapíše volné místo na disku a systemctl --failed do souboru nebo do journalu. Použijte vlastního uživatele, Type=oneshot, alespoň dvě bezpečnostní volby a Persistent=true. Otestujte pomocí systemctl start, prohlédněte si výstup v journalu a zapište si skóre z systemd-analyze security. Vložte svůj .service a .timer a odpovězte na otázky v kontrolním seznamu.
Úkol O6.3: Vlastní služba s časovačem
Tento úkol provádíte sami; nikdo ho nekontroluje. Odškrtněte, co jste udělali, a označte úkol jako splněný.
S Persistent=true se úloha po spuštění systému dodatečně provede. Skóre pod 6 je pro první službu dobré; oprávnění k zápisu jen přes ReadWritePaths.
Vaše zaškrtnutí a poznámky zůstávají pouze v tomto prohlížeči; nikam je neposíláme. Pokud jste přihlášeni, ukládáme v sekci Moje kurzy pouze to, že jste úkol splnili.
Doporučujeme k přečtení
- Příručka k DirectAdmin 15.1: Naplánované úlohy: automatické spouštění úloh
- Manuál
systemd.exec(5)(User=, ProtectSystem=, NoNewPrivileges=): https://manpages.debian.org/trixie/systemd/systemd.exec.5.en.html - Manuál
systemd.timer(5)(OnCalendar=, Persistent=): https://manpages.debian.org/trixie/systemd/systemd.timer.5.en.html - Manuál
systemd.time(7)(časové plány): https://manpages.debian.org/trixie/systemd/systemd.time.7.en.html
