S již hotovým toolchainem jsme připraveni pustit se do tvorby našeho vlastního systému. Tvořit se bude opět ve speciálně nastaveném shellu v našem standardním systému, takže během dlouhých kompilací můžeme bez problému pracovat tak, jak jsme zvyklí, jen si občas odskočíme do terminálu a zadáme další kompilaci.
Chrootnuté prostředí
Toolchain se tvořil v prostředí speciálního uživatele, k tomuto účelu vytvořeného, z toho důvodu, že bylo potřeba mít některé systémové proměnné nastavené trochu jinak než obvykle, ale jinak se používaly nástroje z hostitelského systému. V takovém případě je tvorba pod speciálním uživatelem vhodná. Při tvorbě systému je to ale jinak. Nyní potřebujeme mít zcela izolované prostředí, jakýsi systém v systému. Toho se dá celkem snadno docílit prostým přesvědčením shellu, že jistý adresář, dle našeho výběru, je „kořenový“, tedy „/“. Od toho okamžiku se celá podvětev stromové struktury adresářů, jejímž nejvyšším bodem je onen námi vybraný adresář, chová jako samostatná stromová struktura a my nemáme možnost jakkoliv přistoupit k čemukoliv mimo ni. Takovými přesvědčovacími metodami disponuje příkaz chroot a v knize LFS je použit takto: chroot "$LFS" /tools/bin/env -i \ HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \ PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \ /tools/bin/bash --login +h
kde proměnná LFS představuje adresář s přimountovaným LFS oddílem. Ostatní parametry zařídí v pořadí, jak jsou uvedené – vynulování systémových proměnných v chrootnutém prostředí, nastavení nových proměnných HOME, TERM, PS1, a PATH. Poslední parametr spustí bash a vypne jeho hashování (ono +h). Co to znamená to hashování? Bash si normálně poznamenává spouštěné příkazy, aby nemusel pořád procházet adresáře v proměnné PATH. V případě, že je použit takto poznamenaný příkaz, neprohledává se PATH, ale rovnou se spustí tentýž konkrétní program jako v předchozím případě. Při tvorbě systému ale chceme, aby se nově vytvořené nástroje začaly používat okamžitě. Z toho důvodu je hashování vypnuto, takže Bash musí poctivě procházet adresáře v PATH jeden za druhým. Vzhledem k tomu, že adresář /tools/bin je až na konci tohoto seznamu, bude vždy použit každý nově nainstalovaný program okamžitě po nainstalování jeho binárek do některého z adresářů /bin, /usr/bin
, /sbin nebo /usr/sbin – prostě proto, že je tam Bash najde dříve.
Při tvorbě toolchainu v minulém díle jsme se drželi dokumentace LFS víceméně doslovně. Vymýšlet nějaké úpravy u toolchainu nemá totiž moc smysl, vzhledem k tomu, že jde pouze o dočasné nástroje, které použijeme ke zbudování vlastního systému a vzápětí je odstraníme. Ale toto již neplatí při budování vlastního systému. Zde už je nutno brát LFS knihu poněkud odlišně. Jistě, i nadále kniha provádí procesem tvorby systému krok po kroku s vysvětlením všech voleb a příkazů. Ale účelem knihy není, aby tvůrce slepě následoval její postup. Kdepak. Kniha pouze předkládá učebnicový model s tichým předpokladem, že si ho každý přiohne svým představám a potřebám. Tvůj systém – tvá pravidla.
LFS postup se snaží držet se obecně zavedených linuxových standardů The Linux Standard Base a taktéž stromová struktura v něm použitá ctí zásady Filesystem Hierarchy Standard , tak aby byl výsledný systém jednoduše použitelný standardním způsobem. Je dobré si uvědomit, že odchylovat se od standardů je samozřejmě povolené, jenom je třeba k tomu přistupovat promyšleně a být smířen s tím, že to většinou znamená práci navíc.
Správa software v novém systému
Před samotnou tvorbou systému je vhodné si nejprve pořádně promyslet pár věcí. Především ty, které by se později měnily docela těžko. Zde platí ono staré dobré pořekadlo – dvakrát měř a jednou instaluj.
První ze dvou základních věcí, které bychom měli dobře uvážit, je, jakým způsobem budeme v našem systému spravovat software. Dokumenty LFS si totiž s touto věcí hlavu nelámou, a vše se v nich instaluje přímo do systému pomocí make install. Problémem tohoto způsobu je, že my vlastně nevíme, co se kam nainstalovalo, a nemáme tudíž způsob, jak to lehce, v případě potřeby, odstranit. Taktéž dohledat informace o tom, co je vlastně nainstalováno, a k čemu patří jaký soubor, je takřka nemožné.
Dalo by se celkem dlouho diskutovat, zda je vůbec nějaké takové organizování software potřeba. Jistě v dokonalém světě by potřeba nebylo – všechno by se totiž do systému pomocí make install hladce nainstalovalo, nikde by nic s ničím nekolidovalo a všechno by hned fungovalo. A nikdy bychom to nepotřebovali odinstalovávat. Protože svět není dokonalý, nefunguje to tak. Stane se, že po nainstalování daný program nefunguje tak, jak jsme si představovali a je třeba jej odinstalovat. Chtít mít proces přidávání a odebírání software plně pod kontrolou je, dle mého názoru, dobré rozhodnutí.
Protože tvoříme svůj vlastní systém, můžeme si sami rozhodnout, jakým způsobem budeme proces správy kontrolovat. Pojďme se tedy podívat, jaké máme možnosti. Následující výčet není ani zdaleka úplný, jistě existují i další způsoby. Pokud o nějakých víte, podělte se o ně s námi v případné diskusi pod článkem.
Balíčky
Nejpoužívanějším systémem správy software jsou klasické balíčkovací systémy, známé z většiny distribucí. Aplikace či knihovny či cokoliv dalšího pak přicházejí do systému jako balíčky. Tyto balíčky příslušný balíčkovací systém vezme, rozbalí, soubory z nich nakopíruje na definované lokace a udělá si záznam ve své databázi, co nainstaloval a kam. Tyto informace jsou nám potom kdykoliv na požádání k dispozici a taktéž slouží při případném odinstalovávání. Stačí požádat balíčkovací systém, aby ze systému odebral ten a ten balíček, on se podívá do databáze, vytáhne si informace, které soubory je třeba odstranit a tyto odstraní, načež si odstraní i záznam o tom, že ten balíček vůbec kdy viděl.
Distribuční balíčky v sobě, kromě samotného software, nesou spoustu dalších informací. Důležitý je především seznam závislostí. Drtivá většina programů totiž ke svému fungování potřebuje knihovny, které autor programu při jeho vývoji použil. Distributor, který vytváří balíček, do něj tedy uvede, na jaké knihovně je program závislý. Takže při pokusu o instalaci tohoto programu chytré balíčkovací systémy napřed stáhnou z distribučních repozitářů požadovanou knihovnu a nainstalují ji, takže následně instalovaný program ji už v systému má, a může být zkompilován. Ty méně user-friendly aspoň upozorní, že chybí ona knihovna, a dokud ji nenainstalujeme, tak nám instalaci programu nepovolí (pokud nepoužijeme násilí). A pak jsou taky takové, které si s nějakými závislostmi hlavu nelámou vůbec, a je na uživateli, aby si zjistil, co k provozování programu potřebuje, a taky to obstaral.
Pokud se rozhodneme v našem systému použít balíčkovací systém, budeme si balíčky vytvářet sami. Není tedy třeba vůbec uvádět žádný seznam závislostí. Nebudeme totiž mít v tomto případě k dispozici žádný repozitář a balíčkovací systém by tak neměl jak tyto závislosti řešit. Není to vlastně ani potřeba, protože si program kompilujeme sami ve svém systému a tudíž tam ony potřebné knihovny už být musí, jinak by se nám program zkompilovat ani nepovedlo. Narazit můžeme, leda pokud bychom z nějakého důvodu něco odinstalovali – při samotné odinstalaci by nás totiž nic neupozornilo na fakt, že to, co mažeme je potřeba pro deset dalších programů, které bez toho nebudou fungovat. Ale na to bychom vzápětí přišli velmi rychle sami.
Pěkný návod jak ve svém systému zprovoznit a používat debianovský dpkg, je na LinuxFromScratch.org
Samostatné adresáře
Další možností je mít pro každou aplikaci zvláštní adresář. Při instalaci se prostě místo standardního umístění nechá aplikace nainstalovat do námi určeného adresáře. K tomuto účelu může dobře posloužit například adresář /opt. Tento způsob vyžaduje drobné poinstalační úpravy. Minimálně proměnnou PATH je potom potřeba doplnit o nový adresář, a do /etc/ld.so.conf dodat záznam o novém adresáři s knihovnami, pokud chceme, aby o nich systém „věděl“. Odinstalace by pak probíhala prostým smazáním adresáře a odstraněním těchto úprav. Informace o tom, co je vlastně v systému nainstalované, by pak bylo možné zjistit třeba pomocí ls /opt
Systém založený na majitelích souborů
Velice zajímavá myšlenka je využít odlišných majitelů souborů. Pro názornost – pro instalaci mplayeru se vytvoří speciální uživatel se jménem mplayer a pod tímto uživatelem se provede samotná instalace. Soubory, které tak budou nainstalovány, budou mít majitele mplayer, čímž jsou jednoznačně a lehce odlišitelné od souborů jiných aplikací. Na tomto základě pak probíhá celá správa software, která má díky tomu některá velmi zajímavá specifika a možnosti. Například instalace neprobíhá s právy roota, což opatrnější z nás určitě ocení. Domovské adresáře těchto uživatelů se dají krásně použít pro přehledné uložení hromady informací vztahující se k danému balíčku včetně zdrojových kódů. Situace, kdy jedna aplikace při instalaci přepíše nějaký soubor jiné aplikace, jsou takřka vyloučené. Taktéž odstranit při odinstalaci soubor patřící jiné aplikaci není zrovna snadné. Detaily jsou výborně popsány v samostatném článku.
Vlastní řešení
V neposlední řadě si můžeme nějaký ten systém pro správu software vytvořit sami. Klidně za pomoci Bashe a základních GNU utilit. Napsat si pár šikovných skriptíků, které by v podstatě simulovaly základní funkce klasických balíčkovacích systémů nemůže být pro zdatnějšího linuxáka příliš velký problém. V podstatě jde pouze o to udržet si přehled, kam co instalujeme, takže při instalaci si toto prostě někam poznamenat a následně to na základě tohoto záznamu dokázat odinstalovat. Je to sice tak trochu objevování kola, ale fantasii a iniciativě se meze nekladou.
Taky je samozřejmě možné použít kombinaci některých výše uvedených způsobů, klidně i všech. Například základní systém LFS instalovat s prefixem /usr, jak je tomu v knize, přímo natvrdo do systému, každou další aplikaci do vlastního adresáře v /opt a knihovny pomocí nějakého balíčkovacího systému umísťovat do /usr/local. Jediné, na čem záleží, je, abyste se v tom sami vyznali, a aby se vám to používalo pohodlně.
Tou druhou základní věcí, kterou je třeba rozhodnout hned na začátku, je rozložení adresářů. Jak už jsem psal, LFS staví na osvědčeném modelu dle FSH, ale nic nám nebrání si tu strukturu adresářů přestavět plně podle svých představ. Je ale třeba myslet na to, že s modelem FSH počítají všichni vývojáři a ačkoliv jde drtivá většina software donutit, aby se nainstalovala tak, jak my chceme a kam chceme, může to být v některých případech opravdu pracné. Některé aplikace mají dokonce natvrdo nastavené, co kde mají hledat, a pak je třeba speciálně pro ně vytvářet příslušné symlinky. Už se nejspíš budu opakovat, ale rozhodnutí je plně na tvůrci systému, jeho budoucím uživateli, a vyhovující je tedy to, co jemu samotnému vyhovuje.
Tvorba systému
Poté co se rozhodneme jak budeme software spravovat, můžeme se konečně pustit do samotné tvorby vysněného systému. Chrootneme se do tvůrčího LFS prostředí, vytvoříme si na disku strukturu adresářů a pustíme se do kompilace balíčků tak jak jdou za sebou v knize LFS. Ačkoliv máme knihu při ruce, uzpůsobujeme si veškeré parametry skriptu configure tak, aby vyhovovaly naším potřebám, především pokud jsme nějakým způsobem měnili strukturu adresářů, je třeba na toto myslet a příslušnými parametry skriptu configure definovat nová umístění. Připomínám, že veškeré parametry, kterými můžeme toto nastavovat, se dají zjistit spuštěním
configure s parametrem –help. Při třetím kroku svaté trojice postupujeme v souladu se systémem správy software, pro který jsme se rozhodli.
Tentokrát se začíná instalací hlavičkových souborů Linuxového API. Ty se vydolují ze zdrojových kódů linuxového jádra, nejlépe toho, který posléze použijete k běhu systému. Následuje opětovné přeložení a instalace glibc. Tentokrát už opravdu finální verze. Zdrojové kódy obsahují i možnost otestování zkompilovaných binárek, zda se vše přeložilo správně. Je rozumné tento test v tomto okamžiku provést, ačkoliv to o dost prodlouží celý proces instalace. Je lepší případné problémy odhalit hned, než později pracně zjišťovat při podivném chování systému, kde je chyba.
Následují staré známé binutils, opět s doporučením provést kontrolní testy. Po nich přijdou na řadu dvě matematické knihovny a následuje finální verze gcc. A pak už to jede jeden balíček za druhým, celkem jich je asi padesát. I za předpokladu, že nenarazíte na žádný problém, tak to trvá dlouho (není to na jeden večer, spíš na víc), a je to celkem monotónní a únavná práce. Doporučuji doplnit tuto základní kolekci software o nějaký internetový prohlížeč, například lynx, elinks nebo něco podobného a taky Midnight Commander nám v novém systému, který nebude disponovat žádným GUI jistě prokáže neocenitelné služby. Naopak se dá předpokládat, že GRUB je již nainstalován v rámci systému, ve kterém tvorbu LFS
provádíme, a můžeme ho tedy s klidem vynechat aspoň do chvíle, než se rozhodneme odstranit starý systém a z nového udělat náš hlavní.
Poté co je vše zkompilováno a nainstalováno, zbývá vytvořit bootovací skripty a udělat náš nový systém bootovatelný. LFS používá klasický SysVinit, známý z většiny distribucí, a přichází s kolekcí vlastních bootovacích skriptů. Existují ale i jiné možnosti než SysVinit, například Upstart nebo Initng. Klasická struktura skriptů používaná s SysVinit se možná může zdát někomu zbytečně nepřehledná a složitá. Při tvorbě vlastního systému můžeme zjednodušit boot a jeho konfiguraci, jak jen to jde. Vzhledem k tomu, že tvoříme systém ušitý na míru našim potřebám, může být plně dostačujícím řešením klidně i jeden jediný hlavní skript plus po jednom skriptu na každý runlevel. Pro inspiraci, jak vytvořit přehledné a jednoduché bootovací skripty, se můžete podívat na LinuxFromScratch.org.
Nyní nás čeká velké finále. Máme nainstalován všechen potřebný software, napsané bootovací skripty, zbývá zkompilovat a nainstalovat jádro neboli kernel, příslušně upravit menu.lst v našem hostitelském systému a restartovat. V menu GRUBu vybereme náš nový systém a pak už se můžeme kochat rychlým bootem našeho nového, vlastního systému.
Tak a máme nový linuxový systém, co s ním teď dál? Pracovat v textovém režimu sice může někomu stačit a tím zde jeho cesta víceméně končí, ale pokud chceme plnohodnotný desktopový systém, čeká nás ještě spousta práce. A o té si povíme v příštím, závěrečném díle.