Úvod do systemd

8.11.2014

Ačkoliv je zde systemd již delší dobu, nepřestávají filosofické ani technické diskuse na toto téma, kdy se střetávají příznivci tohoto subsystému s jeho odpůrci.

Poněvadž nehodlám naskakovat na vlnu nenávisti k tomuto systému, ani nepatřím k jeho skalním příznivcům, nebudu zde vystupovat v roli evangelisty či hatera. Jeho existenci beru na vědomí stejně jako to, že s ním chtě nechtě přicházím do styku.

Následující článek (možná články) se tedy bude zabývat úvodem do systemd, jeho použití (jak je u mne obvyklé - s přihlédnutím k implementaci v distribuci CentOS) a jeho možnostmi.

Předpokládám znalosti problematiky initscriptů, filosofie linuxových služeb a chuť při čtení článku zkoumat svůj vlastní systém, zejména pokud používáte odlišnou distribuci, kde se může lišit umístění některých souborů a i celkový koncept použití systemd, i když ten se spíše snaží o co největší unifikaci.)

Poznámka: je obtížné vybírat informace pro úvodní seznámení s tímto systémem, a proto prosím laskavého čtenáře o komentáře pod článek, které si případně vyžádají úpravu článku při nepochopení některých vlastností tohoto systému nebo architektury nebo účelu příkazů. Zjistil jsem, že někteří administrátoři považují systemd za složitý, což považuji za omyl, který je daný variabilitou systemd.

Co by však tento článek měl přinést (podobně jako u ostatních bylo o tématu napsáno již mnohé, existují různé manuály a velmi sofistikované články)? Zejména to, že se zde nepouštím do přílišných složitostí, zaměřuji se na praktické použití a článek je psán tak, že pokud použiji termín, o kterém jsem se nezmínil, vrátím se na začátek k definici základních pojmů a tento doplním.

Základní pojmy a architektura

Protože každý má a bude mít jiný názor na to, co je na systemd dobrého a co je jeho výhoda a co opak, nebudu zde tuto kategorizaci provádět, protože každému vyplynou vlastní závěry z toho, co zná nebo z dalšího textu.

Pro úplné nováčky: systemd je subsystém linuxového prostředí, který: realizuje první proces systému (tedy nahrazuje proces init) a zajišťuje správu velké části systému, včetně běhu jednotlivých služeb a nastavení systému, žurnálování stavu jednotlivých služeb a komponent systému, realizuje základní komponenty systému, atd.

Tedy některé nejviditelnější vlastnosti pouze bodově (zbytek bude vidět z architektury a použití):

  • paralelní start démonů
  • kontrola stavu procesů
  • start služeb on demand
  • závislosti mezi službami, zdroji, apod.
  • integrace s PAM
  • čím dál tím větší provázanost s kernelem
  • snaha o co největší normalizaci prostředí
  • binární žurnálování
  • snaha o kompatibilitu či koexistenci se standardními init scripty i o co největší začlenění subsystémů pod systemd
  • deklarativní popis konfigurace
  • snaha o zvýšení bezpečnosti
  • snaha o převzetí funkce některých subsystémů (služeb)
  • dnes už (kromě výjimek) podpora ve všech distribucích
  • snaha o zjednodušení správy systému v některých aspektech
  • podpora desktopových prostředí
  • kontejnery (jistá v tuto chvíli nedokonalá obdoba LXC, zkrátka jistá forma paravirtualizace)

atd…

SysemVInit má samozřejmě i další svoje konkurenty, i když ti nejsou tak podporovaní nebo využívaní jako systemd a samozřejmě se liší tím, jaké funkce zastávají:

  • Upstart (v některých distribucích předchůdce systemd)
  • runit
  • initng
  • launchd
  • eINIT
  • minit
  • cinit
  • Mudur
  • s6
  • Epoch

Poznámka: z toho, co bylo řečeno, je zjevné, že systemd nemá za cíl nahradit pouze init a initscripty, ale má mnohem větší ambice, jak ostatně také uvidíme dále.

Poznámka: tato kapitola je pouze pomůckou pro lepší porozumění. Pokud však spíše potřebujete systemd pouze používat, přeskočte ji na kapitolu “Vybrané příklady použití”.

Architektura systemd je komplexní. Jak je vidět na obrázku níže, začíná na úrovni kernelu a pokračuje přes knihovny a vlastní jádro systemd až k jednotlivým unitám a nástrojům pro správu.

Protože tím nechci obtěžovat v další kapitole, zmíním se o významu několika komponent:

Cgroups

Je systém pro správu zdrojů (paměť, CPU, I/O,…). Systemd využívá cgroups pro řízení a sledování procesů, nastavování limitů zdrojů pro urcčité skupiny procesů. Mimo jiné zajišťuje, že proces nemůže (třeba double-forkem) opustit rodičovský systemd a stejně tak lze lépe kontrolovat ukončování procesů apod.

Pro zájemce více o cgroups na http://en.wikipedia.org/wiki/Cgroups nebo v dokumentaci RedHatu v manuálu https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/pdf/Resource_Management_and_Linux_Containers_Guide/Red_Hat_Enterprise_Linux-7-Resource_Management_and_Linux_Containers_Guide-en-US.pdf.

Dbus

S touto komponentou jste se určitě již setkali. Slouží pro komunikaci mezi procesy (tedy InterProcess Communication - IPC), které si tak tedy mohou vyměňovat zprávy, čímž tyto procesy mohou být modulárnější, mohou separovat oprávnění, atd.

Opět pro více informací se podívejte na http://en.wikipedia.org/wiki/D-Bus.

Unixové sockety

Unix domains socket jsou dalším známým nástrojem pro předávání informací mezi procesy oběma směry. Sockety jsou reprezentovány soubory typu socket.

Units

Pro administrátora asi nejdůležitější pojem. Unity jsou základní konfigurační složkou systemd. Pomocí nich jsou definovány jednotlivé úlohy, které jsou v rámci systemd vykonávány (například definice jednotlivých služeb, což je z pohledu administrátora serveru asi nejčastější setkání s tímto pojmem, nicméně je zde mnohem širší záběr).

Unit je několik typů (popis uvádím pouze tam, kde význam není zjevný):

  • service (služba systému, např.: httpd, postfix, atd.)
  • target (skupina unit určená pro seskupování pro hromadnou manipulaci, např. realizaci runlevelů)
  • socket
  • device
  • mount
  • automount
  • path
  • snapshot (uložený stav ostatních unit)
  • swap
  • timer (časovač systemd)
  • scope (externě vytvořené procesy)
  • slice (skupina hierarchicky organizovaných jednotek pro správu procesů - viz cgroups)

Unity jsou realizovány konfiguračními soubory, jejichž umístění závisí na distribuci. V CentOSu jsou (pro system mode) v adresářích:

  • /usr/lib/systemd/system/ - distribuované s RPM balíčky
  • /run/systemd/system/ - vytvářeny za běhu
  • /etc/systemd/system/ - vytvářené administrátorem (má přednost před konfiguračními soubory v /usr/lib)

Na desktopu (respektive pro user mode) najdete i další adresáře, ve kterých jsou definice unit, ale to je již mimo rozsah tohoto článku.

Při použití unit uvádíme jejich název a typ oddělené tečkou, např.: httpd.service (jak jste již mohli vidět v předchozích článcích, když jsme pomocí manažera systemd, systemctl, restartovali tuto službu). V některých případech můžeme typ vynechat.

Pokud narazíte na pojmenování unity ve stylu getty@tty1.service, potom jde o použití šablony, která usnadňuje definici např. více instancí stejných služeb.

Journal

Pro svou činnost systemd samozřejmě potřebuje i žurnál o činnosti jednotlivých unit. K tomu mu slouží vlastní žurnálovací subsystém, který je aktivní od začátku startu kernelu až do shutdownu. Má několik vlastností, jako je logování zpráv do podadresářů v adresáři /run/log/journal, předávání zpráv do syslog démona, což umožňuje i zprávy z žurnálu posílat na jiný server, zajímavou vlastností je binární formát ukládání zpráv a jejich zabezpečení, které nedovoluje (aniž by to administrátor poznal) modifikovat záznamy žurnálu. Pro práci se žurnálem slouží program journalctl, ale zprávy z žurnálu jsou využity i ve výstupech programu systemctl.

Runlevely

Toto je pojem SystemVinitu, který administrátoři znají a systemd je reimplementuje jako unity typu target. Jak bylo řečeno, target je typ unity, který sdružuje několik unit dohromady. Toho se dá s úspěchem využít i pro realizaci runlevelů, které řeší hromadný start nebo ukončení služeb při přechodu do konkrétního runlevelu. Aby administrátoři netápali, byly využity i symlinky, které ukazují na targety vlastní systemd a jsou pojmenovány tak, aby připomínaly původní runlevely:

runlevel targets
0runlevel0.target → poweroff.target
1runlevel1.target → rescue.target
2runlevel2.target → multi-user.target
3runlevel3.target → multi-user.target
4runlevel4.target → multi-user.target
5runlevel5.target → graphical.target
6runlevel6.target → reboot.target

Účel jednotlivých targets (tedy postaru runlevelů) je samovysvětlující.

Dependencies

Aneb závislosti. Jak jsme si řekli ve výčtu vlastností, tak jednou z nich je, že použití unit může mít (například start služby) závislost na jiné unitě. Díky konfiguračním souborům unit může být resolving závislostí vyřešen korektně. Typickou závislostí je, že jedna unita může být nastartována až ve chvíli, kdy již beží jiná. Dependency může být i pouze volitelná.

Vybrané příklady použití

Uvedeme si příklady několika základních i dalších příkazů pro jednotlivé scénáře použití. Za základní příkazy považuji ekvivalenty nejčastěji používaných příkazů, které používáme se systémem init.

Pro valnou většinu uživatelů nebo administrátorů jsou nejdůležitějšími příkazy takové, které jim umožní nastartovat, restartovat a zastavit službu a nastavit jí, aby startovala po spouštění systému. Můžeme si je zde uvést jako nové alternativy k předchozímu ovládání služeb v rámci SystemVinit.

Ad-hoc příkazy pro management služeb (u systemd jsou v některých případech uvedeny i varianty):

servicepříkaz systemctlpopis
service name startsystemctl start name.servicespuštění služby name
service name stopsystemctl stop name.servicezastavení služby
service name restartsystemctl restart name.servicerestart služby
service name condrestartsystemctl try-restart name.servicerestart služby, pokud služba běží
service name reloadsystemctl reload name.serviceznovunačtení konfigurace
service name statussystemctl status name.servicetest, zda služba běží
systemctl is-active name.service
service –status-allsystemctl list-units –type service –allzobrazení stavu všech služeb

Příkazy ovlivňující chování služeb po startu:

SystemVinit příkaz chkconfigpříkaz systemctlpopis
chkconfig name onsystemctl enable name.servicepovolení startu služby i po restartu sytému
chkconfig name offsystemctl disable name.servicezákaz startu služby po restartu systému
chkconfig –list namesystemctl status name.servicezjištěni stavu
systemctl is-enabled name.service
chkconfig –listsystemctl list-units-files –type servicevýpis stavu všech služeb

Toto byl seznam asi nejčastějších úkonů, které administrátor se službami prováděl v distribuci CentOS.

Při použití jednotlivých variant příkazu systemctl (což je mimochodem manažer systemd a nejspíše nejčastější příkaz systemd, který budeme používat), uvidíme, že jeho výstup je rozsáhlejší, než původní SystemVinit varianta. Například pokud se nezdaří start služby, je vypsáno, abyste zjistili příčinu pomocí příkazu “systemctl status name.service”, který využívá právě záznamů z journallingu systemd, stejně tak, jako poskytne informace o cgroups vlastnostech dané služby.

Příkazy pro práci s runlevely jsou prováděny tedy také pomocí příkazu systemctl:

SystemVinit stylsystemd stylpopis
runlevelsystemctl list-units –type targetzjištění aktuálního runlevelu/naloadovaných targetů
telinit runlevelsystemctl isolate name.targetzměna runlevelu/targetu

I zde jsou samozřejmě odlišnosti. Při zjištění, jaké jsou aktuálně naloadované targets jich uvidíme více a “runlevel” poznáme tak, že se mezi nimi objeví jeden z targets, který je v tabulce v podkapitole Runlevely.

Defaultní target, který je uplatněn při startu systému se dozvíme pomocí příkazu:

systemctl get-default

a pro jeho nastavení použijeme:

systemctl set-default name.target

Defaultní target také zjistíme tak, že si necháme vypsat symlink z fs a zjistíme, kam ukazuje:

# ls -l /usr/lib/systemd/system/default.target
lrwxrwxrwx 1 root root 16 Oct 23 23:47 /usr/lib/systemd/system/default.target -> graphical.target
# ls -l /etc/systemd/system/default.target
lrwxrwxrwx. 1 root root 37 Oct 14 03:55 /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target

Vidíme zde, že definice unit v /etc/systemd/ má přednost před /usr/lib/systemd/, jak už jsme si řekli dříve, poněvadž výstup z příkazu “systemctl get-default” byl “multi-user.target”.

Změnu targetu na rescue nebo emergency provedeme jedním z příkazů (jsou zde vždy dvě varianty, které jsou opět samovysvětlující):

systemct rescue
systemctl --no-wall rescue
systemctl emergency
systemctl --no-wall emergency

Pokud chceme server/počítač obecně vypnout nebo jinak ovlivnit jeho power-management, pak se zde opět nabízí srovnání se starou variantou:

starý příkaznový příkaz systemd
haltsystemctl halt
systemctl –no-wall halt
poweroffsystemctl poweroff
systemctl –no-wall poweroff
rebootsystemctl reboot
systemctl –no-wall reboot
pm-suspendsystemctl suspend
pm-hibernatesystemctl hibernate
pm-suspend-hybridsystemctl hybrid-sleep

Vzhledem k tomu, že toto byly asi nejčastější ekvivalenty příkazů, které administrátoři původně používali, je na čase zmínit se i o dalších, specifických použití systemd.

Vzdálené volání systemctl

Jedním z užitečných použití je vzdálené volání příkazu systemctl, které provedeme jedním z následujících příkazů:

systemctl --host username@hostname command
systemctl -H username@hostname command

Tyto příkazy způsobí, že bude vytvořeno ssh připojení ke vzdálenému stroji a zavolán příkaz systemctl s příslušným commandem.

Použití journalu

Journalling je, jak již bylo popsáno poměrně mocný nástroj. Jeho existence se projeví například ve výstupu příkazu “systemctl status name.service”, například “systemctl status httpd.service”, kde vypisuje poslední zprávy journalu vztahující se k dané službě (jeho použití je explicitně doporučeno například, pokud startujeme nějakou službu a start nedopadne dobře). Nicméně existuje i samostatný příkaz journalctl a některým z jeho použití se budeme v této podkapitole věnovat.

Poznámka: journalctl pro výpis zpráv z žurnálu používá pager, abychom stále nemuseli přes pipe používat příkazy more nebo less nebo nějaký jiný pager. Jednotlivé parametry je možné samozřejmě různě kombinovat. Počet zpráv, které jsou v journalu uchovávané se řídí konfigurací.

Online sledování zpráv journallingu

Pokud používáme pouze standardní syslog a chceme vidět, co se online děje, použijeme příkaz “tail -f /path/to/a/file”, který nám zobrazí poslední řádky logu a průběžně načítá další. Podobnou věc můžeme provést následujícím příkazem, ovšem s tou výhodou, že zprávy můžeme omezit na například (ale nejen) zprávy od konkrétní služby:

journalctl -f -u name.service

Parametr “-f” znamena follow a “-u” (není poviný, parametr “-f” můžeme použít i samotný) říká od jaké unity chceme vidět logy z žurnálu. Pokud vynecháme suffix “.service”, doplní se automaticky.

Prohlížení všech zpráv journallingu

Asi nejjednodušší použití:

journalctl

doplní automaticky parametr –all a vypíše celý žurnál.

Prohlížení všech zpráv journallingu pro určitou službu

journalctl -u name.service

Zobrazení zpráv kernelu

journalctl -k

Zobrazení zpráv od určitého data a času

journalctl --since="YYYY-MM-DD hh:mm:ss"
journalctl --since="1 hours ago"

Reverzní zobrazení journalu

journalctl -r

Toto byla pouze ukázka toho, co journalctl umí, více samozřejmě najdete v manuálové stránce journalctl(1).

Debugging startu unit i systému

V případě SysVinit-u měl člověk poměrně snadnou prácí sledovat, co se děje od zavlečení kernelu do paměti. Příkazem dmesg si zobrazil zprávy kernelu, podíval se (pokud to předem nevěděl) do inittabu na string initdefault a prošel si všechny rc scripty, které se v daném defaultním runlevelu pouštěly a samozřejmě i ty spouštěné před a po nich a dále programy spouštěné přímo initem.

V případě systemd je situace poněkud odlišná. Nicméně i zde máme šanci, jak se dozvědět, co se dělo při bootu systému.

Detekce chyb při startu služeb

systemctl --failed
systemctl --state=failed

Tyto příkazy zobrazí unity, které nenastartovaly z důvodu nějaké chyby. Pokud chybu opravíme a unitu (službu) spustíme, tento příkaz ji již nezobrazí.

Oproti tomu příkaz

systemctl

vypíše všechny nastartované unity.

Informace o časové délce startu služeb

systemd-analyze time
systemd-analyze blame
systemd-analyze plot >obrazek.svg

První příkaz vypíše na konzoli, kolik času zabral start systému, druhý kolik času zabraly jednotlivé unity a třetí vyrobí přehledné grafické vyjádření včetně časových návazností.

Zapnutí debug mode

Konfigurační položka grubu v souboru “/etc/default/grub”:

GRUB_CMDLINE_LINUX="systemd.log_target=kmsg systemd.log_level=debug" 

nastaví debuggovací režim. Zde bych si jen dovolil upozornit, abyste toto činili po prostudování dokumentace.

Zjištění, na jaké ulohy se čeká

systemctl list-jobs

Informace o procesech a cgroups

Jedna z možností, jak se dozvědět něco o běžících procesech a jejich vztahu k cgroups je příkaz:

ps xawf -eo pid,user,cgroup,args

jehož alternativou je:

systemd-cgls

Pro užitečnost výstupu z těchto příkazů je vhodné se podívat na vlastnosti cgroups do výše uvedených zdrojů.

Podobným příkazem s online výstupem je příkaz:

systemd-cgtop

kde můžeme řadit výstup podle jednotlivých zdrojů pomocí kláves “m” (memory), “c” (CPU), “i” (I/O) a “p” (path).

Výpis všech targets

systemctl list-units -t target --all

Bez parametru “–all” vypíše pouze aktivní targets.

Zákaz spouštění unit (maskování)

Unity můžeme disablovat, což způsobí, že nenastartují při bootu systeému. Pokud však chceme dovést zákaz spouštění služeb do extrému, můžeme použít maskování, což provedeme příkazem:

systemctl mask unit

Opačnou operaci provedeme:

systemctl unmask unit

Je vhodné použít příkaz:

systemctl daemon-reload

který řekne manažeru systemd, že má znovunačíst konfiguraci všech unit.

Posílání signálů procesům služeb

Tyto příkazy pošlou signál procesům/procesu specifikované služby:

systemctl kill -s SIGKILL name.service
systemctl kill -s HUP --kill-who=main name.service

přičemž první varianta pošle signál KILL všem procesům služby a druhá signál HUP pouze hlavnímu procesu služby.

Zjišťování závislostí mezi unitami

Příkaz:

systemctl show -p "Wants" name.typeofunit
systemctl list-dependencies

nám ukážou (v případě prvního) unity jejichž aktivaci způsobí aktivace specifikované unit a v případě druhého zobrazí strom závislostí mezi jednotlivými unitami.

Místo klíčového slova “Wants” můžeme použít i další, které se smí vyskytovat v konfiguračních souborech unit. Viz manuálová stránka systemd.unit(5).

Přidání další instance služby

Protože po instalaci CentOSu máme k dispozici právě jeden virtuální terminál (spuštěné jeden getty proces), můžeme mít zájem na tom, aby jich bylo více. Toho dosáhneme použití šablon, o kterých jsme si říkali v podkapitole Units.

systemctl enable serial-getty@ttyS2.service
systemctl start serial-getty@ttyS2.service

Před zavináčem je název šablony a za ním je název konkrétní instance služby. Samozřejmě nejsme omezeni pouze na tuto jednu konkrétní službu.

Tímto náš dnešní článek končí. Opět chci připomenout, že měl za úkol pouze pomoci administrátorům v základních úkonech, které souvisí se systemd a seznámit je s jeho vlastnostmi. Další články na toto téma budou pokračovat.

  • obsah/linux_obecne/systemd_uvod.txt
  • Last modified: 2018/10/17 21:40
  • by profors