Hlavní navigace

Nebojte se systemd: vytváření jednotek

Jan Knížek 6. 6. 2016

Minule jsme se naučili jednotky ovládat pomocí příkazu systemctl. Dnes si ukážeme jejich vytváření, formát konfiguračních souborů a nastavení stejné pro všechny typy jednotek.

Formát konfiguračních souborů

Jednotky, které jsou instalovány z repozitářů, a tedy by je uživatel neměl měnit, sídlí v /usr/lib/systemd/system, resp. uživatelské v /usr/lib/systemd/user. Vlastní systémové jsou standardně v /etc/systemd/system. Uživatelské jsou v /etc/systemd/user, které jsou přístupné pro všechny uživatele, a v ~/.systemd/user  pro každého uživatele zvlášť.

Konfigurační soubory jsou inspirovány soubory s příponou .desktop, které nalezneme například v GNOME (pozor, systemd na rozdíl od těchto souborů povoluje specifikovat hodnotu vícekrát, standardní parsery tedy nemusí fungovat). Tento formát je snadno čitelný jak pro uživatele, tak pro počítače. Soubor je rozdělen na pojmenované sekce uvozené řádkem [jméno]. V každé sekci je pak seznam hodnot ve formátu jméno parametru=hodnota. Řádka uvozená # popř ; je komentář.

Zde si ještě doplňme minulý díl. Pokud chceme načíst novou konfiguraci nějaké jednotky, stačí spustit příkaz systemctl daemon-reload, který aktualizuje všechny jednotky. Příkaz, který by aktualizoval jen jednu konkrétní, neexistuje. Pozor na záměnu se systemctl reload jednotka, který aktualizuje konfigurační soubory týkající se té jednotky, ne konfigurace systemd. Vše vysvětlí příklad. Reload jednotky Apache přečte httpd.conf, apache.service se aktualizovat nebude. Oproti tomu daemon-reload přečte konfiguraci souboru apache.service, tedy např. změní závislosti.

Pokud je hodnotou seznam, rozumí se oddělený mezerami. Také je možné specifikovat tuto hodnotu na několika řádcích, výsledek je pak sjednocení těchto seznamů. Pokud jako hodnotu předáme prázdný řetězec, dojde k vynulování aktuálního seznamu. Tedy v následujícím příkladu bude v parametru Documentation seznam „man:ls man:systemd“.

Documentation=file:/home/knezi/ahoj man:od
Documentation=
Documentation=man:ls
Documentation=man:systemd

Jednotky obecně mají sekci [Unit], ve které nalezneme parametry nezávisející na typu, tedy např. popis či závislosti. Dále [Install], ve které jsou informace pro instalaci jednotky. Tato sekce není interpretována systemd za běhu, ale až při použití příkazů enable/disable, které slouží pro povolení/zakázání spouštění jednotky po startu počítače. Poslední sekce je již závislá na typu konkrétní jednotky a představíme si ji později.

Příklad jednotky typu služba mající všechny tři sekce:

[Unit]
Description=Console Shell
Documentation=man:sulogin(8)
After=systemd-user-sessions.service plymouth-quit-wait.service
Before=getty.target

[Service]
Environment=HOME=/root
WorkingDirectory=-/root
ExecStart=-/usr/bin/sulogin
ExecStopPost=-/usr/bin/systemctl poweroff
Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

[Install]
WantedBy=getty.target

Pro snažší psaní konfiguračních souborů se hodí zvýrazňování syntaxe. Pro textový editor VIM stačí stáhnout již hotové zvýrazňování syntaxe. V Arch Linuxu je přímo balíček vim-systemd. Zdrojové soubory jsou na adrese fedorapeople.org/cgit/wwo­ods/public_git/vim-scripts.git (přímý odkaz do repozitáře git://fedorapeople.org/ho­me/fedora/wwoods/public_git/vim-scripts.git). Stačí zkopírovat soubory ftdetect/systemd.vim, ftdetect/udev.vim do adresáře /usr/share/vim/vimfiles/ftdetect a syntax/systemd.vim, syntax/udev.vim do /usr/share/vim/vimfiles/syntax. Pro zapnutí zvýrazňování stačí ve VIMu pustit příkaz  :syntax on.

Sekce [Unit]

Základním parametrem je Description, což je popis, který se objeví například ve výpisu všech jednotek. Všimněme si, že zde není parametr pro jméno. To se odvozuje od jména konfiguračního souboru. Parametr Documentation obsahuje seznam URI oddělených mezerami. URI mohou být typu http[s]://, file:, man:, info:. Přičemž příkaz systemctl help jednotka zobrazí první dostupnou manuálovou stránku (tedy file:, http[s]:// přeskakuje). Celý parametr Documentation se objeví ve výpisu příkazu  systemctl status jednotka.

Závislosti

Řešení a spouštění závislostí řeší tzv. minimální transakční systém. Kdykoliv je jednotka aktivována či deaktivována, je přidána spolu se všemi rekurzivními závislostmi do dočasné transakce. Poté se otestuje, jestli transakce obsahuje cykly. Pokud ano, systemd odstraní všechny postradatelné závislosti a také odstraní ty, které by mohly aktivovanou jednotku zastavit. Poté se zkontroluje, jestli není transakce v konfliktu s nějakou právě prováděnou a nakonec, pokud je vše v pořádku, je přidána do spouštěcí fronty. Speciálně pokud není možné transakci vyřešit, je odmítnuta ještě před jejím prováděním a nezůstane tak v žádném mezistavu.

V systemd se doporučuje používat automatické závislosti všude, kde je to možné. K tomuto účelu se používá mechanismus socket-based activation. Princip si představíme na pulseaudio.service. Jednotka může komunikovat s ostatními pomocí speciálních souborů (tzv. socket). K této jednotce vytvoříme další jednotku typu socket (tedy pulseaudio.socket), kterou nastartujeme po startu počítače. Ve chvíli, kdy potřebujeme pulseaudio.service použít, přistoupíme k socket souboru jednotky pulseaudio.socket, která při prvním přístupu spustí  pulseaudio.service.

Pokud z nějakého důvodu automatické závislosti použít nemůžeme nebo nechceme, má systemd propracovaný systém explicitních závislostí. Vše přehledně shrnuje následující seznam. Jen poznamejme, že všechny parametry jsou seznamy hodnot, tedy pro ně platí chování popsané výše.

Requires
Při aktivaci se aktivují všechny jednotky specifikované v tomto seznamu. V případě že selže aktivace některé jednotky ze seznamu nebo nějaká selže za běhu, bude deaktivována i tato. Tento parametr nedefinuje pořadí spouštění jednotek, spuštěny budou všechny najednou, pokud to neurčí jiný parametr.
Wants
Slabší varianta Requires. Funguje stejně, jen nevadí, pokud nějaká závislost selže. Dokumentace tuto variantu doporučuje.
After,Before
Jednotka je aktivována až po startu nebo před startem definovaných jednotek. Tento parametr nedefinuje explicitní závislost, jen určuje pořadí spouštění. Více viz příklad.
Conflicts
Když je tato jednotka aktivována, jsou zastaveny všechny konfliktní a naopak.

Ukážeme si modelový příklad. Pokud spustíme jednotku tlp příkazem systemctl start tlp.service, spustí se jednotky bluetooth.service a NetworkManager.service. Řádka After=multi-user.target bluetooth.service NetworkManager.service zajistí, že se tyto jednotky nejdříve spustí a teprve až když jsou spuštěné, jednotka tlp.service se začne spouštět. Díky tomu, že závislosti jsou definované parametrem Wants=, spouštění bude pokračovat i pokud by spouštění některé závislosti selhalo. Vidíme, že pro vhodné nastavení používání závislosti je nutné použít kombinaci Requires/Wants a After/Before.

[Unit]
Description=TLP system startup/shutdown
Wants=bluetooth.service NetworkManager.service
After=multi-user.target bluetooth.service NetworkManager.service
Before=shutdown.target

[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/usr/bin/tlp init start
ExecStop=/usr/bin/tlp init stop

[Install]
WantedBy=multi-user.target

Ještě poznamenejme, že výše uvedené nastavování závislostí Requires a Wants je možné nastavit i bez nutnosti úpravy konfiguračních souborů. Pokud bychom chtěli přidat závislost jednotce tlp, můžeme vytvořit adresář /etc/systemd/system/tlp.service.wants a symbolický odkaz z tohoto adresáře na jednotku, kterou chceme mít jako závislost tlp. Stejný mechanismus funguje i s Require. Tohoto faktu se využívá při instalaci jednotek. Viz níže.

V krátkosti ještě zmíníme několik dalších parametrů, další podrobnosti může čtenář nalézt v manuálových stránkách man systemd.unit. Pokud jednotka selže, spustí se příkaz v parametru OnFailure. Tento parametr je vhodné použít například pro upozornění administrátora v případě selhání jednotky důležité pro běh systému.

Pokud jednotka potřebuje ke svému běhu nějaký adresář či soubor na jiném oddíle, nemusí být tento oddíl při startu ještě připojen. To vyřeší parametr RequiresMountsFor, který určuje, že jednotka může být spuštěna až ve chvíli, kdy je daná cesta připojena do souborového systém. Také je možné specifikovat podmínky, za kterých může být jednotka spuštěna. Jsou to parametry začínající Condition, popř. Assert, kterými je možno například určit, že jednotku je možné spustit pouze na některých architekturách nebo že počítač musí být napájen z elektrické sítě.

Sekce [Install]

Nejdůležitějšími parametry jsou WantedBy a RequiredBy, které říkají, kam se mají přidat závislosti při příkazu systemctl enable. Pokud chceme nějakou jednotku spouštět po startu, typicky nastavíme WantedBy=default.target, popř. WantedBy=multi-user.target. Při systemctl enable netctl.service se nastaví závislost multi-user.target na netctl.service a díky tomu se netctl spustí po startu počítače. Závislosti se nastavují pomocí symbolických odkazů, takže není nutné editovat žádné soubory. Při disable se zase odkazy odstraní.

Úprava jednotek

Pokud potřebujeme upravit nějakou jednotku, která je dodávaná v repozitářích, nemůžeme upravit její konfigurační soubor, protože by byl při příští aktualizaci přepsán. Jednou možností je zkopírovat jednotku do adresáře /etc/systemd/system, který má vyšší prioritu. Tím se ale připravíme o aktualizace. V systemd existuje mechanismus umožňující přepsat jen některé parametry. Pro každou jednotku můžeme vytvořit adresář  jmeno.d. Jednotka je načtena standardně a poté jsou aplikovány všechny soubory s příponou .conf v této složce. Soubor je standardně rozdělen na sekce (jen neobsahuje sekci [Install]) a řádky jsou přidány do původní konfigurace.

Pokud tedy například chceme kompletně předefinovat jednotky, které budou spuštěny před tlp.service, parametr After vymažeme parametr a nadefinujeme vlastní:

/etc/systemd/system/tlp.d/change.conf

After=
After=jednotky...

Šablony

Často je potřeba použít nějakou jednotku v několika instancích (kupříkladu terminály). K tomu se dají použít šablony, které mají stejné konfigurační soubory jako běžné jednotky. Odlišeny jsou zavináčem na konci jména. Pokud v systemd pracujeme s jednotkou obsahující zavináč (ve tvaru jmeno@parametr.typ), je hledán soubor jmeno@.typ a pro odlišení konkrétní instance se použije parametr. V systemd je standardně šablona getty@.service a pro třetí terminál slouží jednotka odvozená z této šablony pojmenovaná  getty@tty3.service.

V šablonách je ještě proti běžným jednotkám možné použít meta informace o konkrétní jednotce. Tedy např. %i je identifikátor označující parametr. V našem případě je nahrazen tty3. Více v man systemd.unit  v sekci  SPECIFIERS.

Šablonami jsme vyčerpali dnešní téma. Na shledanou u následujících dílů, ve kterých si představíme konkrétní typy jednotek.

Našli jste v článku chybu?

6. 6. 2016 14:45

Trochu mě štve jak spusta lidí používá unix=*bsd. Třeba takový solaris se startd a mac os s launchd se vydali taky poněkud jinou cestou.

7. 6. 2016 15:14

Sten (neregistrovaný)

No, jestli máš tak kvalitní „informace“ i o systemd (a zatím tomu vše nasvědčuje), pak se tvým komentářům nedivím… RHEL 7 vyšel před dvěma roky.

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Lupa.cz: Není sleva jako sleva. Jak obchodům nenaletět?

Není sleva jako sleva. Jak obchodům nenaletět?

Lupa.cz: Avast po spojení s AVG propustí 700 lidí

Avast po spojení s AVG propustí 700 lidí

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0