O čem seriál bude? Náplní prvního dílu je vysvětlení standardního spouštěcího mechanismu Linuxu (pro pokročilé uživatele nic nového). Nikoli vyčerpávajícím způsobem, od toho jsou manuálové stránky, ale především v souvislosti s dalšími díly. Druhý díl se bude zabývat nedostatky tohoto systému a řešením pomocí daemontools od D.J. Bernsteina. Ve třetím dílu půjdeme ještě dál – zcela nahradíme init runitem Gerrita Papeho.
Init
Loading Linux..................
Po nastartování jádra spustí jádro první proces, init. Tento proces je rodičem všech ostatních procesů. V Linuxu náležejí procesy do jediného stromu, jehož je init kořenem; zda je tomu tak i teď, můžete zkontrolovat příkazem pstree:
# pstree -ap
Init je současně prvním i posledním běžícím procesem, což znamená, že je zodpovědný za start i ukončení systému. Protože má toto privilegium, nezabije ho ani signál SIGKILL. Init sám je program, nalezneme ho v adresáři /sbin. Na jeho konfigurační soubor /etc/inittab se nyní podíváme blíže. Je vcelku nudný, sestává z několika řádků, každý ve formátu
id:runlevels:action:process
id je unikátní 1–4znakový identifikátor řádku, runlevels jsou čísla úrovní, pro které řádek platí,action je akce (…) a process je příkaz, který se má vykonat.
Co init umí?
Spoustu věcí. V dalších dílech zjistíme, že možná zbytečně mnoho. Jeho hlavním úkolem je totiž zajistit spuštění všech ostatních programů.
-
vykoná příkaz při inicializaci systému
si::bootwait:/etc/init.d/boot
zde je příkazem skript /etc/init.d/boot. Bude vykonán jako úplně první. Úkolem skriptu je připojit disky, načíst moduly do jádra, provést různé kontroly atp.
-
definuje základní úroveň běhu (runlevel)
id:5:initdefault:
zde se dá ovlivnit, zda počítač nastartuje do grafického režimu, či nikoli (v našem případě ano). Runlevelů je standardně 6, přičemž 0, 1 a 6 jsou vyhrazené.
0 způsobí vypnutí počítače (halt), 1 znamená jednouživatelský režim, 2 víceuživatelský režim bez NFS, 3 víceuživatelský režim bez grafického rozhraní, 4 není použito, 5 víceuživatelský režim s grafickým rozhraním a 6 reboot
Po proběhnutí inicializace se můžeme přepnout do jiného runlevelu příkazem telinit (případně jen init):
# telinit 3 # telinit 5
-
vykoná příkaz podle úrovně běhu (runlevelu)
l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 … l6:6:wait:/etc/init.d/rc 6
Je vidět, že příkaz, tedy skript /etc/init.d/rc, převezme kontrolu nad inicializací všech úrovní. Akce wait zaručí spuštění příkazu pro daný runlevel pouze jednou a init počká, až příkaz doběhne.
-
spouští getty
Getty je program, který zobrazí login na konzoli.
1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2 3:2345:respawn:/sbin/mingetty tty3 4:2345:respawn:/sbin/mingetty tty4
proces mingetty bude spouštěn v úrovních 2 až 5, na konzoli 1 až 4. „Spouštěn“ píšu kvůli akci respawn – jakmile dojde k jeho ukončení (odhlášením z konzole), init spustí mingetty znovu, tj. opět se zobrazí login.
-
reaguje na některé klávesové kombinace
ca::ctrlaltdel:/sbin/shutdown -h now
-
reaguje na výpadek proudu
pf:12345:powerfail:/sbin/shutdown -h now
init.d skripty
Řekněme, že init proběhl. V našem případě spustil nejdříve skript /etc/init.d/boot a následně přešel do runlevelu 5. Proto nyní spouští /etc/init.d/rc 5, který se postará o zbytek inicializace…
INIT: Entering runlevel: 5
V tomto bodě se inicializační proces liší u jednotlivých distribucí. Většina vychází buď z modelu System V, nebo BSD. Principiálně se však odehrává totéž – v určitém pořadí jsou spouštěny skripty z /etc/init.d. Zjednodušeně: co skript, to služba. Službou je myšleno apache, mysql, ale pozor! na rozdíl od Windows i grafické rozhraní (služba xdm).
Jde o shellové skripty, každý s funkcemi start, stop, restart, reload a status. Používat je lze i ručně
# /etc/init.d/apache start # /etc/init.d/xdm restart # /etc/init.d/mysql stop
Úrovně běhu (runlevely)
Bylo by dost mepraktické, kdybychom museli po zapnutí počítače startovat služby ručně. Od toho jsou runlevely. Jde vlastně o seznam služeb, které mají být spuštěny, případně ukončeny. Jak již bylo napsáno výše, seznamů je standardně šest, přičemž při inicializaci se použije základní, viz initdefault v /etc/inittab.
Mandrake, RedHatu nebo SuSE
řeší runlevely pomocí adresářů. Adresáře mají v názvu číslo runlevelu a obsahují symlinky na skripty v /etc/init.d. Tj. každý adresář jako by obsahoval jen vybrané skripty z /etc/init.d.
Ukážeme si příklad runlevelu 5, tedy adresáře /etc/init.d/rc5.d. Vidíme v něm symlinky:
K05×dm → /etc/init.d/xdm
K06cron → /etc/init.d/cron
…
S08sshd → /etc/init.d/sshd
S09portmap → /etc/init.d/portmap
S15mysql → /etc/init.d/mysql
Po přechodu do runlevelu 5 budou všechny skripty postupně spouštěny v abecedním pořadí (stará se o to skript /etc/init.d/rc, viz inittab).
- Nejprve přijdou na řadu symlinky s K na začátku. K jako kill – ukončí služby, které případně běžely v předchozím runlevelu, ale v runlevelu 5 běžet nemají.
- Následně budou vykonány symlinky S, startovací.
- Dvojčíslí má význam pro zajištění pořadí spouštění (abecední).
Službu můžeme do runlevelu přidat ručně, ale znamená to jednak určit závislosti na ostatních (pořadí spouštění) a druhak vytvořit oba symlinky s S i K. Různé distribuce mají různé nástroje, které toto provedou za nás. Přidávací nástroj SuSE kupříkladu zjišťuje závislosti ze speciálních hlaviček v init.d skriptech.
Gentoo
používá dokonalejší systém. Také spouští skripty z /etc/init.d, ale k určení pořadí neslouží jejich názvy. Místo toho je po startu spuštěn /sbin/depscan.sh, který načte závislosti ze skriptů a tyto závislosti uloží kamsi mimo. Vše se pak na jejich základě řeší automaticky, a to v případě potřeby. Má to výhody – ručním nastartováním služby se zároveň nastartují všechny služby závislé. Navíc si inicializační systém pamatuje, která služba byla nastartována a která ne, z čehož vyplývá další vlastnost – při restartu služby se nejprve ukončí všechny na ní závislé, služba se restartuje, načež se ukončené služby opět nastartují. Příkladem je restart sítě, který ukončí apache, mysql,…
# /etc/init.d/net.eth0 restart
Gentoo však neřeší situaci, kdy služba spadne – nadále totiž předpokládá, že běží, a odmítá ji spustit. Je nutné mu přímo přikázat, aby ji považoval za vypnutou
# /etc/init.d/apache zap
Závěr
Každý inicializační systém má svá pro a proti. V Gentoo je vyspělý, ale zase mnohem složitější a citlivější (užil jsem si s ním své). Ani jeden neumožňuje současné spouštění služeb, které vede k rychlejšímu startu systému.
Na alternativní řešení se podíváme příště. Existují již dlouho, jsou spolehlivější a jednodušší. Bohužel, velké distribuce setrvávají u zažitých. To ovšem neznamená, že je nemůžete používat.
Odkazy:
Source Mage GNU/Linux – VII aneb Není init jako init – I
System V init
Gentoo init system
Daemontools
Runit
Autor je lektorem OKsystem.