systemd a služby

units, systemctl, targets, enable vs start.

systemd je první program, který jádro spustí po startu (dostane PID 1), a je to „dirigent" celého systému: nastartuje, hlídá a zase zastavuje služby (daemony — programy běžící na pozadí). Nahradil starý SysV init se změtí spouštěcích skriptů. Když pochopíš jednu věc — rozdíl mezi spustit teď (start) a spouštět při každém bootu (enable) — přestane ti půlka záhad kolem serverů dávat smysl a druhá půlka zmizí úplně.


Pár pojmů na úvod

  • Daemon = program běžící na pozadí bez okna, obvykle donekonečna (webserver, databáze, SSH). Jméno často končí na dsshd, nginx, crond.
  • PID 1 = první proces v systému. Jádro po startu spustí právě systemd a dá mu číslo 1; ten pak nastartuje všechno ostatní. Když PID 1 spadne, spadne celý systém.
  • Unit (jednotka) = jedna věc, kterou systemd spravuje — služba, časovač, přípojný bod… Popsaná je textovým souborem (.service, .timer…), viz níže.
  • systemctl = tvůj hlavní nástroj na ovládání systemd. Vším, co se služeb týče, mluvíš přes něj.
  • journald = logovací část systemd. Sbírá výstup všech služeb do jednoho místa; čteš ho přes journalctl (vlastní kapitola o logách).
  • target = pojmenovaná skupina unitů, náhrada za staré „runlevely". Např. graphical.target „přitáhne" všechno potřebné pro grafické přihlášení.

Co je unit a jaké má typy

Všechno, co systemd spravuje, je unit — a poznáš ho podle přípony souboru. Není to abstraktní: každý unit je obyčejný textový soubor, který si můžeš přečíst.

  • .service — služba/daemon. Nejčastější typ. Říká, co spustit (ExecStart), jak to restartovat při pádu a na čem to závisí.
  • .timer — časovač, moderní náhrada cronu. Spouští nějaký .service podle času nebo intervalu (např. „každý den ve 3:00" nebo „15 minut po startu").
  • .socket — naslouchá na síťovém portu nebo socketu a službu nastartuje, až když někdo přijde (socket activation). Šetří zdroje.
  • .target — skupina unitů, kterou zapneš jako celek (viz sekce o targetech). Zhruba jako starý runlevel.
  • .mount — přípojný bod disku (co se má připojit kam). systemd umí spravovat i mountování.

💡 Nemusíš znát všechny nazpaměť. 95 % času budeš řešit .service, občas .timer. Zbytek si najdeš, až ho potkáš.


systemctl — příkazy, které budeš psát denně

systemctl je brána ke všemu. Základní sada, kterou si zapamatuj:

systemctl status nginx      # jede to? kolik paměti? poslední řádky logu?
systemctl start nginx       # spusť TEĎ
systemctl stop nginx        # zastav TEĎ
systemctl restart nginx     # stop + start (tvrdý restart)
systemctl reload nginx      # jen znovunačti konfiguraci, bez shození služby
systemctl enable nginx      # spouštěj automaticky při každém bootu
systemctl disable nginx     # už nespouštěj při bootu
systemctl is-enabled nginx  # spustí se to po rebootu? (enabled / disabled)
systemctl is-active nginx   # běží to právě teď? (active / inactive)
systemctl list-units --type=service   # co všechno teď běží

status je tvůj první krok při každém problému — ukáže, jestli je služba active (running) nebo failed, kdy naposledy nastartovala a pár posledních řádků z logu.

💡 Většina těchhle příkazů (start, stop, enable…) mění stav systému, takže je potřebuješ pouštět pod sudo. Čtecí příkazy (status, is-enabled, list-units) fungují i bez něj.


⚠️ start vs enable — tohle si přečti dvakrát

Junioři to pletou pořád, a je to zdroj číslo jedna záhadných „po rebootu to přestalo jet":

  • start = spusť službu teď, jednorázově. Platí do dalšího vypnutí/rebootu. Po restartu počítače je pryč.
  • enable = zaregistruj službu, aby se spouštěla automaticky při každém bootu. Nespustí ji hned teď — jen řekne „příště po startu ji nahoď".

Jsou to dvě nezávislé věci. Chceš-li obojí (běž teď a i po rebootu), buď je zavolej obě, nebo použij zkratku:

sudo systemctl enable --now nginx   # enable + start naráz
sudo systemctl disable --now nginx  # disable + stop naráz

🚩 Klasická past: nasadíš službu, uděláš jen start, všechno jede, jdeš spát. Za týden server spadne a restartuje se — a služba nenajede, protože nikdy nebyla enable. Server je „nahoře", ale appka mrtvá. Vždy si po nasazení ověř systemctl is-enabled tvoje-sluzba.


Napíšeme si vlastní službu

Unit soubor je obyčejné INI. Vlastní služby patří do /etc/systemd/system/. Řekněme, že máš skript nebo aplikaci myapp, kterou chceš držet trvale naživu — vytvoříš /etc/systemd/system/myapp.service:

[Unit]
Description=Moje appka
After=network.target          # po inicializaci síťové vrstvy (ještě nemusí být plně nahoře)

[Service]
ExecStart=/usr/local/bin/myapp --port 8080
Restart=on-failure            # když spadne, systemd ji nahodí zpátky
RestartSec=5                  # počkej 5 s před restartem
User=myapp                    # neběž jako root — vlastní neprivilegovaný účet

[Install]
WantedBy=multi-user.target    # při enable se navěsí na tenhle target

⚠️ Pozor: network.target neznamená „síť je nahoře a má IP" — jen že se síťová vrstva konfiguruje. Když se služba při startu potřebuje připojit ven nebo naslouchat na konkrétní IP, použij Wants=network-online.target + After=network-online.target. Se samotným network.target může naběhnout dřív, než je síť plně funkční, a hned spadnout.

Tři sekce, tři role: [Unit] popis a závislosti, [Service] co a jak spustit, [Install]kam to navěsit při enable. Jakmile soubor vytvoříš nebo změníš, musíš systemd říct, ať ho znovu načte, jinak o změně neví:

sudo systemctl daemon-reload        # načti nové/změněné unit soubory
sudo systemctl enable --now myapp   # zapni při bootu + spusť teď
systemctl status myapp              # zkontroluj, že jede

🚩 Na daemon-reload se strašně snadno zapomíná. Upravíš unit, dáš restart, ono to jede po staru a ty nechápeš proč. Pravidlo: změnil jsem .service soubor → daemon-reload.


Targets místo runlevelů

Staré Unixy měly „runlevely" (čísla 0–6) pro režimy systému. systemd to nahradil targety — pojmenovanými skupinami unitů, které dávají větší smysl:

  • multi-user.target = plně funkční systém, síť, služby, ale jen textová konzole (typický server).
  • graphical.target = to samé + grafické přihlašování a plocha (typický desktop).
  • rescue.target / emergency.target = záchranné režimy pro opravy.

Který target systém nabíhá po startu, zjistíš a nastavíš takhle:

systemctl get-default                     # graphical.target nebo multi-user.target?
sudo systemctl set-default multi-user.target   # server bez grafiky → šetři zdroje
sudo systemctl isolate graphical.target   # přepni do jiného targetu za běhu

💡 Proto v [Install] píšeš WantedBy=multi-user.target — chceš, aby se tvoje služba spustila vždy, když systém dojede do „normálního provozu". Skoro každá běžná služba tam patří.


Systémové vs uživatelské unity

To, co jsme řešili zatím, jsou systémové unity — běží pod rootem/systémem, startují při bootu a spravuje je sudo systemctl. Vedle toho má systemd i uživatelskou vrstvu: služby, které běží jen pod tvým účtem a jen když jsi přihlášený.

systemctl --user status syncthing   # tvoje osobní služba, bez sudo
systemctl --user enable --now foo    # unit v ~/.config/systemd/user/

Rozdíl: systémové unity žijí v /etc/systemd/system/, uživatelské v ~/.config/systemd/user/. Uživatelské se hodí na věci, co nepotřebují root (osobní sync, hudební démon), a nepletou se do systému. (Pozn.: aby uživatelská služba běžela i po odhlášení, musí být povolený „lingering".)


Když služba nejede

Postup je vždycky stejný a nikdy si nedomýšlej — systemd i journal ti řeknou přesně proč:

systemctl status myapp        # 1) stav + posledních pár řádků logu
journalctl -u myapp           # 2) celý log JEN téhle služby
journalctl -u myapp -e        # skoč na konec (nejnovější)
journalctl -u myapp -f        # sleduj živě (jako tail -f)
journalctl -u myapp --since "10 min ago"   # jen posledních 10 minut

Ve status hledej řádek Active: (je tam failed?) a případný „exit code". Detaily — proč proces spadl, jaká výjimka, jaký chybějící soubor — najdeš v journalctl -u. Práci s logy do hloubky rozebírá samostatná kapitola o logách a journald.


Failure modes — časté omyly začátečníků

  • Zapomenutý enable. Služba jede, protože jsi dal start, ale po rebootu je pryč (nikdy nebyla navěšená na boot). Řeš enable --now, ověř is-enabled.
  • Zapomenutý daemon-reload. Upravil jsi .service, ale systemd pořád jede podle staré verze v paměti. Po každé editaci unitu → sudo systemctl daemon-reload.
  • restart místo reload (a naopak). reload jen přenačte konfiguraci bez výpadku — ale ne každá služba ho umí. Když reload „nic neudělá", potřebuješ restart. Naopak zbytečný restart shodí spojení uživatelů; kde stačí reload, použij ho.
  • Špatný WantedBy. Když v [Install] navěsíš službu na target, který systém nenabíhá, enable „projde", ale po bootu se nic nespustí. Pro běžné služby chceš multi-user.target.
  • Editace unitu v /usr/lib/systemd/system/ místo override v /etc. Soubory od balíčků jsou v /usr/lib/... a update balíčku ti je přepíše — tvoje úpravy zmizí. Nikdy je needituj přímo: použij sudo systemctl edit služba (vytvoří override v /etc/systemd/system/služba.d/), který má přednost a přežije aktualizaci.

🛠️ Cvičení

  1. Stav služby. Vyber si nějakou běžící službu na svém systému (třeba sshd, NetworkManager nebo cron) a zjisti tři věci: jestli právě běží, jestli se spustí po rebootu a kdy naposledy nastartovala. Kterými příkazy?
  2. start vs enable vlastními slovy. Vysvětli kamarádovi na dvě věty, proč služba, kterou „přece spustil" (start), po rebootu nejede. Jak to opravit jedním příkazem?
  3. Napiš vlastní .service. Vytvoř unit, který při každém bootu spustí libovolný skript (klidně /usr/local/bin/hello s echo). Jaké tři kroky uděláš po vytvoření souboru, aby to opravdu jelo i po rebootu?
  4. Target systému. Zjisti, do jakého targetu tvůj systém nabíhá. Kdyby to byl server bez monitoru, jakým příkazem bys ho přepnul, ať zbytečně nestartuje grafiku?
  5. Detektiv u rozbité služby. Služba je ve stavu failed. Popiš dva příkazy, kterými zjistíš, proč spadla, a řekni, čím se liší (co ti ukáže každý z nich).
Náčrt řešení — rozbal, až si cvičení zkusíš sám
  1. Stav službysystemctl status sshd ukáže vše naráz (řádek Active: = běží/failed, čas startu, kus logu). Zvlášť: systemctl is-active sshd (běží teď?), systemctl is-enabled sshd (spustí se po bootu?). Pozor: is-active a is-enabled jsou dvě různé otázky — služba může být active a přitom disabled (jede teď, ale po rebootu ne).
  2. start vs enablestart spustí službu jen jednorázově, do dalšího rebootu; enable ji zaregistruje, aby se spouštěla při každém startu systému. Kdo dal jen start, po rebootu službu ztratí. Oprava: sudo systemctl enable --now sluzba (zapne pro boot i spustí teď). Pozor: enable samotné službu nespustí hned — proto to --now.
  3. Vlastní .service — soubor dej do /etc/systemd/system/hello.service se sekcemi [Unit], [Service] (ExecStart=/usr/local/bin/hello) a [Install] (WantedBy=multi-user.target). Tři kroky: sudo systemctl daemon-reload (načti nový unit) → sudo systemctl enable --now hello (boot + teď) → systemctl status hello (ověř). Pozor: bez daemon-reload systemd o novém souboru neví a enable selže nebo použije starou verzi.
  4. Targetsystemctl get-default vypíše aktuální default (graphical.target / multi-user.target). Na serveru bez grafiky: sudo systemctl set-default multi-user.target a reboot (nebo sudo systemctl isolate multi-user.target za běhu). Pozor: multi-user.target = plná síť a služby, jen bez grafického prostředí — nic „nevypínáš", jen nespouštíš X/Wayland.
  5. Rozbitá službasystemctl status sluzba dá rychlý přehled (stav failed, exit code, posledních pár řádků). journalctl -u sluzba -e ukáže celý log jen té služby až po nejnovější řádky — tam je skutečný důvod pádu (výjimka, chybějící soubor, špatný port). Pozor: status je jen výřez; při hledání příčiny vždy dojdi až do journalctl -u.

🧠 Otázky & odpovědi

Jaký je rozdíl mezi start a enable u služby

start službu spustí teď a jednorázově — platí do dalšího vypnutí nebo rebootu, pak je pryč. enable ji naopak nespustí hned, jen zaregistruje, aby se spouštěla automaticky při každém bootu. Jsou to dvě nezávislé věci a junioři je pletou: nejčastější záhada „po rebootu appka nejede" je přesně tohle — někdo dal jen start a zapomněl enable. Chceš-li obojí naráz, použij sudo systemctl enable --now sluzba.

Co je unit a jaké má nejčastější typy

Unit je jedna věc, kterou systemd spravuje, popsaná textovým souborem — poznáš ho podle přípony. Nejčastější je .service (služba/daemon, drtivá většina tvé práce). Dál .timer (moderní náhrada cronu, spouští služby podle času), .socket (nastartuje službu, až když někdo přijde na port), .target (skupina unitů, náhrada runlevelů) a .mount (přípojný bod disku). Nemusíš je umět všechny — začni u .service a zbytek dohledáš, až ho potkáš.

Proč musím po úpravě unit souboru dělat daemon-reload

Protože systemd si při startu načte unit soubory do paměti a dál pracuje s touto verzí. Když soubor upravíš na disku, systemd o změně sám od sebe neví — pořád jede podle staré. sudo systemctl daemon-reload mu řekne, ať znovu přečte konfiguraci z disku. Teprve pak má smysl dát restart, aby se změna projevila. Pravidlo: změnil jsem .servicedaemon-reloadrestart. Bez toho budeš zírat, proč se úprava neprojevuje.

Kam mám psát vlastní službu a proč ne do usr lib

Vlastní unity a úpravy patří do /etc/systemd/system/. Soubory v /usr/lib/systemd/system/ dodávají balíčky a při aktualizaci se přepisují — kdybys tam něco upravil, update ti to smaže. Když potřebuješ jen doladit službu od balíčku, nekopíruj celý soubor: použij sudo systemctl edit sluzba, který vytvoří malý override v /etc/systemd/system/sluzba.d/. Ten má přednost před originálem a přežije aktualizace. Zjednodušeně: /usr/lib = od výrobce, /etc = tvoje.

Co je target a jak souvisí s runlevely

Target je pojmenovaná skupina unitů, kterou systemd zapíná jako celek — nahradil staré číselné runlevely. multi-user.target znamená plně funkční systém se sítí a službami, ale jen v textové konzoli (typický server). graphical.target je to samé plus grafické přihlášení a plocha (typický desktop). Do jakého targetu systém nabíhá, zjistíš přes systemctl get-default a změníš přes set-default. Proto v [Install] u vlastní služby píšeš WantedBy=multi-user.target — chceš, ať se spustí, jakmile systém dojede do normálního provozu.