Hlavní navigace

Záchrana nebootujícího Linuxu pomocí konzole zavaděče GRUB 2

24. 2. 2022
Doba čtení: 9 minut

Sdílet

 Autor: Depositphotos
GRUB 2 je dnes nejrozšířenějším zavaděčem v linuxovém světě. Umí spoustu šikovných věcí, a pokud ho umíte ovládat, dokáže vás dostat z lecjaké šlamastiky. Třeba když vám Linux úplně odmítá nastartovat.

Role zavaděče v kostce

Zavaděč je obecně kus software, který leží někde na začátku disku a je načten firmwarem základní desky. Ten se dříve nazýval BIOS, dnes je to častěji UEFI. Jeho úkolem je připravit hardware k základnímu běhu, načíst zavaděč a spustit ho. Tím je do jeho rukou předán další osud systému v daném počítači.

Zavaděč má poté důležitý úkol – na základě své vlastní konfigurace načíst ze správného souboru do paměti linuxové jádro a přidat k němu z druhého souboru inicializační ramdisk. Ten obsahuje obraz dočasného operačního systému, který bude později použit k úvodním procedurám potřebným pro spuštění pravého systému. Takhle daleko ale tento článek nezasahuje, zůstaneme u zavaděče. O ramdisku možná někdy příště.

Když jsou oba soubory v paměti, přidá k nim zavaděč do paměti kus konfigurace, které říkáme bootovací parametry. Ty budou sloužit později jádru ke správnému postupu při startu. Tyto parametry se ukládají do přesně dané paměťové struktury zvané Boot Protocol.

Nakonec zbývá poslední krok – spuštění samotného jádra. Pokud se vše povedlo, má jádro v paměti všechna data a informace k tomu, aby dokázalo správně nastartovat a zavést z disku zbytek operačního systému.

Když se to rozbije

Aby šlo všechno takhle hladce, musí proběhnout celá řada kroků, které musí dopadnout správně. Pro ucelenou představu si všechny podstatné kroky projdeme:

  • BIOS/UEFI musí najít základ zavaděče (core), načíst ho do paměti a spustit.
  • GRUB se úspěšně inicializuje a spustí. Už má základní přístup k diskům a souborovému systému.
  • GRUB najde bootovací oddíl, vstoupí do souborového systému a najde svou konfiguraci.
  • GRUB dá uživateli možnost konfiguraci za běhu změnit, buď výběrem z menu nebo vstupem do konzole.
  • Pokud uživatel během vymezeného času nezareaguje, GRUB se začne řídit načtenou konfigurací.
  • GRUB teď může z disku načíst nějaké další moduly pro svou funkci, například pro podporu LVM, RAID, šifrování disků a podobně. Některé moduly už mohou být součástí základu.
  • GRUB na zvoleném oddíle konkrétního disku najde soubor s jádrem a načte ho, poté totéž zopakuje s inicializačním ramdiskem.
  • GRUB ze své konfigurace přečte parametry, které je potřeba předat jádru a uloží je do standardní paměťové struktury.
  • Pokud se všechny kroky podařily, je na čase jádro spustit. Tím role zavaděče končí, jádro jej pak při své činnosti přepíše a jeho paměťové stránky použije pro své účely.

Tohle je skutečně jen rámcový přehled kroků k pochopení kontextu. Ve skutečnosti jsou tu ještě další problémy, které musí GRUB řešit. Například, zda jej firmware desky zavedl celý nebo jen jeho část (zavaděč zavaděče), která pak musí ve vlastní režii načíst zbytek. Tímhle se teď ale zabývat nemusíme.

Nejčastější problém, který v celém procesu nastane, je nemožnost z GRUBu zavést správně systém. Buď nám nenastartuje linuxové jádro nebo jej sice načteme, ale start se pak někde zasekne a jádro vyhlásí panický stav (kernel panic). Zavaděč tedy máme, startuje nám, ale nějak se nám rozbila jeho konfigurace, takže není schopen podle ní správně postupovat.

To se stává ve chvílích, kdy začneme hodně žonglovat s oddíly na disku nebo třeba přehodíme disky do jiného počítače či do virtuálního prostředí. Naštěstí je GRUB opravdu hodně pokročilý zavaděč, který je sám o sobě dostatečně mocný na to, aby nám dokázal pomoci z bryndy.

Bavíme se se zavaděčem

GRUB se řídí konfigurací uloženou v souboru /boot/grub/grub.cfg na bootovacím oddíle. Tento soubor ale není určen pro ruční editaci, nýbrž je generován skripty uloženými v adresáři /etc/grub.d/ za pomocí uživatelsky editovatelných parametrů v souboru /etc/default/grub. Tomuto procesu jsem se už před lety věnoval v článku Poznejte boot loader GRUB2.

To podstatné je, že generování konfigurace se spouští příkazem update-grub a skripty jsou schopny detekovat vaše rozložení disků, objevit dostupná linuxová jádra a připravit pěknou konfiguraci včetně uživatelsky ovládaného menu a třeba i upravených barviček. Funguje to velmi dobře, dokud to neselže. Pak nastupuje ruční práce v konzoli.

Nejprve je třeba zavaděč vydráždit, aby se nám ukázal. V některých systémech se vždy při startu na pár sekund objeví jeho menu, takže stačí stisknout třeba šipku dolů a tím se zastaví odpočet do bootu. V jiných distribucích (třeba v Ubuntu) je ale parametr timeout_style nastaven na hidden, takže se nám menu vůbec neukáže a jelikož je parametr timeout zároveň nastaven na 0, boot okamžitě začne bez možnosti zásahu. V takovém případě je potřeba držet od začátku startu počítače klávesu shift, která způsobí zjevení menu. Jsme tam.

V menu v každém případě pravděpodobně uvidíme několik položek, které můžeme zvolit. Ta první bývá obvykle výchozí, pod ní najdeme starší linuxová jádra, která jsou v našem systému dostupná. Ta jsou tam pro případ, kdy by to nejaktuálnější bylo rozbité a nestartovalo by. V takovém případě prostě vybereme nějaké jiné jádro a jsme zachránění. Kromě linuxových jader tu najdeme také třeba možnost nastartovat utilitu memtest nebo jiné operační systémy.

Budeme řešit dvě nejčastější situace: žádná z položek v menu nás nedostane do funkčního systému nebo se menu vůbec neobjeví a rovnou skončíme v konzoli. To se stává v případě, že problém nastal už o krok dříve a GRUB nenašel svou konfiguraci. Pak neví, jak má pokračovat a nechá to na vás. Pokud se menu objevuje a vy potřebujete přejít do konzole, stiskněte jednoduše klávesu c.

Konzole v zavaděči

V tuhle chvíli by na vás měla svítit konzole zavaděče. Ta je velmi mocná a má k dispozici všechny možnosti, jaké má zavaděč samotný. Dokáže procházet disky a oddíly, načítat linuxová jádra a ramdisky, předávat jádru parametry a spouštět operační systémy. Vlastně vám dá plný přístup k souborovým diskům dostupným na daném stroji.

grub>

Touto výzvou vám GRUB oznamuje, že úspěšně nastartoval a dostal se až k načtení modulu normal.mod. Ten obsahuje uživatelsky příjemnou příkazovou řádku, která umí třeba historii a doplňování příkazů pomocí klávesy Tab. Pokud se toho polámalo ještě víc a tento modul nebyl nalezen a načten, skončíte v konzoli s výzvou grub_rescue, která také funguje, ale není tak přívětivá a nemá třeba zmíněné doplňování.

Našim úkolem v každém případě je zastoupit nefunkční konfigurační soubor a ukázat zavaděči, co má odkud načíst a jak to celé spustit. Dobrá zpráva je, že tady nemůžete nic pokazit, protože žádná následující akce není trvalá a nic se nezapisuje na disk. Pokud to uděláte špatně, prostě jen pro tuto chvíli úspěšně nenabootujete. Směle tedy do experimentování, po restartu bude vše v původním stavu.

První kroky v konzoli

Pokud předpokládáme, že uvidíme dlouhé výpisy, které by nám mohly z obrazovky utéct, můžeme si na začátku zapnout stránkovač. Ten zajistí, že se dlouhý výpis zastaví a bude čekat na stisk klávesy.

grub> set pager=1

Teď už se můžeme rozhlédnout po dostupných discích:

grub> ls
(hd0) (hd0,gpt3) (hd0,gpt2) (hd0,gpt1)

Vidíme jeden připojený disk a na něm tři oddíly vytvořené pomocí tabulky GPT. Pokud bychom na stroji měli klasický MBR, viděli bychom například (hd0,msdos1). V tuhle chvíli je to jedno, GRUB umí stejně přistupovat k oběma typům oddílů.

Teď potřebujeme zjistit, který oddíl obsahuje nám tolik potřebná bootovací data. K tomu nám pomůže příkaz ls -l, který vypíše spoustu podrobností o jednotlivých oddílech.

grub>
Device hd0: No known filesystem detected - Sector size 512B - Total size 26327312KiB
        Partition hd0,gpt3: Filesystem type ext* - Last modification time 2022-02-23 00:29:05 Wednesday, UUID 40766b4e-5654-4d71-b420-5e5c992e31ff - Partition start at 527360KiB - Total size 25799680KiB
        Partition hd0,gpt2: Filesystem type fat, UUID 6340-328F - Partition start at 2048KiB - Total size 525312KiB
        Partition hd0,gpt1: No known filesystem detected - Partition start at 1024KiB - Total size 1024KiB

Vidíme detaily o třech oddílech. Jednička neobsahuje žádný souborový systém, protože jde o odkládací oddíl (swap). Dvojka je pak malý oddíl se souborovým systémem FAT, který obsahuje soubory určené pro UEFI – zejména náš GRUB. Konečně trojka obsahuje to, co potřebujeme – souborový systém ext, který obsahuje náš operační systém.

Můžeme se o tom přesvědčit, když si vypíšeme strukturu kořenového adresáře v daném oddílu:

grub> ls (hd0,gpt3)/
lost+found/ boot/ swapfile etc/ media/ bin dev/ home/ lib lib32 lib64 libx32
mnt/ opt/ proc/ root/ run/ sbin snap/ srv/ sys/ tmp/ usr/ var/ cdrom

Jsme doma, vidíme adresáře a soubory. Můžeme se šipkou nahoru k předchozímu příkazu vrátit a nechat si vypsat obsah nějakého dalšího adresáře, třeba (hd0,gpt3)/boot/, ve kterém uvidíme soubory s jádrem. Takto můžeme procházet všechny soubory na disku.

Můžeme si také třeba vypsat některý ze souborů, třeba /etc/os-release je pro nás užitečný a ukáže nám, s jakým operačním systémem máme tu čest.

grub> cat (hd0,gpt3)/etc/os-release
PRETTY_NAME="Ubuntu 21.10"
NAME="Ubuntu"
VERSION_ID="21.10"
…

Bootujeme

Když už se umíme v konzoli pohybovat a umíme se orientovat v dostupných discích, můžeme ručně zvolit správné soubory k bootu a nechat systém nastartovat. Celý postup vypadá takto:

grub> set root=(hd0,gpt3)
grub> linux /boot/vmlinuz-5.13.0-27-generic root=/dev/sda3
grub> initrd /boot/initrd.img-5.13.0-27-generic
grub> boot

Nejprve nastavíme kořenový souborový systém, tedy ten, ze kterého budeme startovat. Ve druhém kroku zvolíme soubor s linuxovým jádrem, které chceme načíst. Rovnou mu musíme předat parametr s odkazem na bootovací oddíl. Pokud to neuděláme, jádro nastartuje, ale nebude umět pokračovat a skončí v panice. Označení sda3 odpovídá našemu hd0,gpt3. Písmeno a označuje první disk, který je v grubovském zápise označen nulou. Samozřejmě musíte parametr upravit podle vlastního rozložení disku.

V dalším kroku načteme do paměti inicializační ramdisk. Ten bude mít v názvu souboru stejnou verzi, jako jádro, pro který byl sestaven. Nezapomeňte, že ve všech zde používaných cestách můžete používat klávesu Tab a nechat GRUB dlouhé cesty automaticky doplnit.

Pokud jsme vše udělali správně, máme už v paměti načteny všechny součásti a stačí příkazem boot nastartovat. Zavaděč skočí do kódu jádra, které začne dělat svou práci a pomocí ramdisku si nakonec připojí kořenový oddíl určený ve svém parametru a z něj nechá systém naběhnout.

Trvalá oprava v systému

Operační systém nám teď nastartoval, ale jen jednorázově. Postup se nikam neuložil a sám se nezopakuje. Pokud chceme problémy odstranit trvale, budeme muset znovu spustit skripty a nechat přegenerovat konfiguraci zavaděče. Je to už velmi jednoduchá operace:

skoleni

# update-grub
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.13.0-27-generic
Found initrd image: /boot/initrd.img-5.13.0-27-generic
Found linux image: /boot/vmlinuz-5.13.0-25-generic
Found initrd image: /boot/initrd.img-5.13.0-25-generic
Found memtest86+ image: /boot/memtest86+.elf
Found memtest86+ image: /boot/memtest86+.bin
done

Pokud potřebujeme znovu na disk zapsat i zavaděč, můžeme to také udělat velmi jednoduše:

# grub-install /dev/sda
Installing for i386-pc platform.
Installation finished. No error reported.

Teď už by měla konfigurace zavaděče odpovídat současnému rozložení disků a nabídce dostupných linuxových jader. Pokud chcete od zavaděče GRUB ještě něco dalšího, rozhodně navštivte kompletní dokumentaci.

Autor článku

Petr Krčmář pracuje jako šéfredaktor serveru Root.cz. Studoval počítače a média, takže je rozpolcen mezi dva obory. Snaží se dělat obojí, jak nejlépe umí.