Operační systémy
Obsah Soubory
Systém v provozu

Start systému

Aktualizováno 8 min čtení 1 555 slov

Start systému: od zapnutí po přihlašovací výzvu

Zmáčkneš tlačítko a za dvacet vteřin máš přihlašovací obrazovku. Devětadevadesátkrát ze sta o tom nevíš nic a nemusíš.

Po sté dostaneš černou obrazovku a jeden řádek textu. Žádný nástroj z téhle wiki ti nepomůže, protože žádný ještě neběží - není shell, není journalctl. Start je jediná část systému, kterou musíš umět opravit poslepu.

Stránka řeší cestu od napájení k přihlašovací výzvě a diagnostiku toho, kde se přerušila. Neřeší, jak jádro funguje potom, co naběhne - na to je Architektury jádra. Předpokládá, že víš, co je proces (Procesy) a co znamená připojit souborový systém (VFS a montování).

Start je řetěz, ne jeden program

Nic takového jako „program, který nabootuje počítač" neexistuje. Existuje řada článků a každý umí přesně jednu věc: najít ten další, nahrát ho do paměti a předat mu řízení. Firmware nezná souborový systém tvého disku, jádro neví, kde má kořen.

Tohle je nejdůležitější věc na celé stránce: když stroj nenaběhne, neptáš se „co je rozbité", ale „kam až se to dostalo". Poslední řádek na obrazovce říká, který článek ještě fungoval. Rozbitý je ten hned za ním.

Šest článků řetězu

1. Firmware

Po zapnutí běží kód z paměti na základní desce, dnes UEFI, dřív BIOS. Otestuje a inicializuje paměť, jádra procesoru a řadiče, pak si z NVRAM přečte seznam zaváděcích položek a nahraje soubor, na který ukazují.

Když nevidíš ani logo výrobce, operační systém s tím nemá nic společného.

2. Zavaděč

GRUB umí to, co firmware ne: číst ext4 a rozumět tvému /boot. Najde jádro (vmlinuz-6.12...) a initramfs (initrd.img-6.12...), nahraje obojí do paměti a předá jádru textový řádek parametrů.

Je to poslední místo, kde do startu zasáhneš rukama - proto je sekce o parametrech níž nejpraktičtější část stránky.

3. Jádro

Obraz jádra je zabalený a začíná krátkým kódem, který rozbalí sám sebe. Pak jádro převezme řízení natrvalo: zapne stránkování (Virtuální paměť a stránkování), rozjede plánovač (Plánování procesů) a připojí /proc a /sys. Skutečný operační systém běží - jen zatím nemá jediný soubor na disku.

4. initramfs

Jádro rozbalí initramfs do paměti a použije ho jako dočasný kořen. Je v něm minimální sada modulů a nástrojů a jediný úkol: podle parametru root= najít skutečný kořenový systém, doplnit, co je potřeba (odemknout LUKS, sestavit RAID, aktivovat LVM), a připojit ho.

5. Přepnutí na skutečný kořen

Když je skutečný kořen připojený, initramfs ho přesune na /, zahodí sám sebe z paměti a spustí /sbin/init - na Debianu symlink na /lib/systemd/systemd. Ten proces dostane PID 1.

6. init

systemd zjistí cíl, kterého má dosáhnout, a paralelně spouští jednotky, na kterých závisí: připojení z /etc/fstab, síť, logování, nakonec přihlašovací výzvu. Tady řetěz končí.

UEFI versus starý BIOS: co se změnilo prakticky

BIOS uměl jedinou věc: načíst prvních 512 bajtů disku a skočit do nich. Do nich (446 bajtů na kód) se nevešlo skoro nic, takže se GRUB sekal na kousky schované do mezer mezi oddíly. Tabulka MBR navíc adresuje bloky 32 bity, což při 512bajtovém sektoru dává strop 2 TiB.

UEFI je proti tomu nudné, a to je jeho přednost. Firmware umí FAT sám, takže na disku stačí EFI systémový oddíl naformátovaný na FAT32, zavaděč je na něm obyčejný soubor s příponou .efi a tabulka oddílů je GPT - bez limitu 2 TiB a bez zaváděcího sektoru.

Secure Boot ověřuje podpis toho, co zavádí - zavaděče a přes něj i jádra. Není to ochrana proti tobě, ale proti kódu, který se chce zavést dřív než jádro a odtud ho obelhat. Cena je, že se zapnutým Secure Bootem ti jádro odmítne nahrát vlastní nepodepsaný modul.

[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS   # ten adresář existuje jen pod UEFI
mokutil --sb-state                                   # zapnutý Secure Boot, nebo ne

Parametry jádra a jak je dopsat

Parametry jsou ten textový řádek, který GRUB předává jádru:

cat /proc/cmdline    # přesně to, s čím tenhle systém nastartoval

root=UUID=... říká, který oddíl je kořen. UUID místo /dev/nvme0n1p2 proto, že jména zařízení se mezi starty mohou přeházet, UUID ne. ro připojí kořen jen pro čtení, aby ho šlo zkontrolovat; init ho pak přepne na zápis. quiet schová hlášky jádra a je první, co při ladění vyhodíš.

single naběhne do záchranného režimu bez služeb. init=/bin/bash je brzda o patro níž: přeskočí systemd a dá ti místo PID 1 shell. nomodeset zakáže jádru přepínat grafický režim - první rozumná reakce na start, který zčerná až po předání řízení jádru.

Do menu GRUBu se dostaneš držením Shiftu, pod UEFI opakovaným mačkáním Esc. Nad zvolenou položkou zmáčkni e, sjeď na řádek začínající linux, na jeho konec dopiš parametr a nastartuj přes Ctrl+X. Změna platí jen pro tenhle jeden start, takže nemáš co rozbít.

Proč initramfs vůbec existuje

Jádro musí připojit kořenový souborový systém. Ovladač řadiče toho disku je ale modul a ten modul leží na tom kořenovém systému. Totéž s LUKS, LVM a RAIDem: abys je otevřel, potřebuješ nástroje, které jsou uvnitř.

Slepice a vejce. initramfs ten kruh přeruší tím, že si moduly a nástroje přiveze s sebou v paměti.

lsinitramfs /boot/initrd.img-$(uname -r) | grep nvme   # je uvnitř ovladač disku?
sudo update-initramfs -u -k all                        # přegenerovat pro všechna jádra

Na Fedoře dělá totéž dracut a obsah vypíše lsinitrd. Klasická chyba je vyměnit jádro, disk nebo šifrování a initramfs zapomenout přegenerovat. Systém běží dál a vypadá zdravě, protože initramfs se používá jedině při startu. Rozsype se to až za týden při restartu a příčinu už nikdo se změnou nespojí.

PID 1 a proč je systemd jiný než skripty

Proces s PID 1 je zvláštní ve dvou věcech. Adoptuje sirotky, tedy procesy, jejichž rodič skončil dřív než ony, a sklízí je, aby nezůstávaly zombie (Procesy). A nesmí skončit: když PID 1 zemře, jádro zpanikaří s hláškou „Attempted to kill init!".

SysV init spouštěl očíslované skripty jeden po druhém a čekal na každý. systemd, v Debianu výchozí od verze 8 (2015), to nahradil trojicí věcí: startuje paralelně podle deklarovaných závislostí, umí připravit soket dopředu a službu spustit až při prvním připojení, a procesy služby drží pohromadě v cgroup, takže je umí spolehlivě zabít i restartovat (Virtualizace a kontejnery).

Jednotka je jeden spravovaný objekt: .service je služba, .target jen pojmenovaný bod, kterého se má dosáhnout.

systemctl list-units --failed    # čím vždycky začni
systemctl status sshd            # stav jednotky včetně posledních řádků logu
journalctl -b -p err             # chyby z aktuálního startu, bez šumu

systemd je kritizovaný za to, kolik věcí do sebe pobral. Ten spor je starý a nemá smysl ho tu otevírat.

Kdy to skončí panikou a kdy jen chybou

Panika znamená, že jádro běží - rozbalilo se, má paměť i plánovač - a narazilo na něco, bez čeho nemůže pokračovat. Nejčastěji na tohle:

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

To není rozbité jádro. To je špatné root=, nebo initramfs bez ovladače toho disku. Naopak zaseknutí v emergency mode znamená, že jádro i systemd běží a rozsypal se jim /etc/fstab - typicky připojení, které selhalo a nemá volbu nofail (VFS a montování).

Tohle je nejužitečnější tabulka na stránce:

Poslední, co vidíš Selhal článek Co s tím
Černo, ani logo firmware hardware, pořadí zavádění
Chybí zaváděcí zařízení firmware → zavaděč smazaný ESP, přepsaná NVRAM
grub rescue> zavaděč přeinstalovat GRUB zvenku
Menu GRUBu, pak černo jádro nomodeset, uber quiet
Unable to mount root fs jádro → initramfs špatné root=, chybějící ovladač
Výzva (initramfs) initramfs kořen nenalezen, neodemčený LUKS
emergency mode, heslo roota init rozbitý /etc/fstab
Naběhne, ale služba chybí init systemctl list-units --failed

Záchrana z živého systému

Když se dovnitř nedostaneš ani přes init=/bin/bash, nastartuj z instalačního USB a vlez si do svého systému zvenku. Klíčové je připojit i /proc, /sys a /dev, jinak uvnitř nefunguje skoro nic.

sudo mount /dev/nvme0n1p2 /mnt              # kořen rozbitého systému
sudo mount /dev/nvme0n1p1 /mnt/boot/efi     # ESP, jinak nemá grub-install kam psát
sudo mount --rbind /dev  /mnt/dev           # rbind vezme i /dev/pts
sudo mount --bind  /proc /mnt/proc
sudo mount --bind  /sys  /mnt/sys
sudo chroot /mnt /bin/bash

Uvnitř pak podle toho, co je rozbité: grub-install --target=x86_64-efi --efi-directory=/boot/efi a update-grub na zavaděč, update-initramfs -u -k all na initramfs, editace /etc/fstab na emergency mode. Souborový systém oprav naopak zvenku a odpojený - fsck -f /dev/nvme0n1p2 na připojeném oddílu ti data dorazí spolehlivěji než původní chyba.

Osm a půl milionu strojů, které se nedaly opravit na dálku

  1. července 2024 rozeslal CrowdStrike aktualizaci datového souboru pro svůj bezpečnostní ovladač běžící v režimu jádra. Soubor shodil ovladač, ovladač shodil systém a stroje spadly do smyčky, ve které padly dřív, než stihly stáhnout opravu. Microsoft odhadl zásah na zhruba 8,5 milionu strojů; odbavovací pulty aerolinek stály celý den.

Oprava byla triviální: nastartovat do nouzového režimu a smazat jeden soubor. Znamenalo to ale, že k 8,5 milionu strojů musel fyzicky přijít člověk. Poučení: co běží před přihlašovací výzvou, si opravu na dálku nedovolí.

Měření startu a co s výsledkem nedělat

systemd-analyze                    # rozpad na firmware, zavaděč, jádro a userspace
systemd-analyze blame              # jednotky seřazené podle doby běhu
systemd-analyze critical-chain     # co na sebe skutečně čekalo
dmesg -T                           # hlášky jádra s čitelnými časy

Ber vážně critical-chain, ne blame. V blame ti vyskočí třeba fstrim.service se třemi minutami, jenže na ten nikdo nečeká - běží stranou a start nezdržel ani o vteřinu.

Nejrychlejší způsob, jak zkrátit start, je nespouštět služby, které nepotřebuješ. systemctl disable na tiskový systém nebo Bluetooth na stroji, kde je nikdo nezapne, ušetří víc než jakékoli ladění. Do závislostí mezi jednotkami nesahej - odměnou je nedeterministický start, který se rozbije jednou za dvacet restartů.

Co si odnést

Start je řetěz šesti článků a každý umí jen najít ten další. Firmware, zavaděč, jádro, initramfs, přepnutí kořene, init.

Diagnostika je otázka „kam až se to dostalo". Poslední řádek na obrazovce určuje článek, ne příčinu.

Panika u Unable to mount root fs znamená zdravé jádro a špatný kořen. Chyba je v root= nebo v initramfs.

emergency mode je skoro vždycky /etc/fstab. Selhalo připojení bez nofail.

initramfs existuje kvůli slepici a vejci. Ovladač kořene leží na kořeni, musí tedy přijet zvlášť v paměti.

Umět v GRUBu zmáčknout e a dopsat parametr je nejcennější dovednost odsud. nomodeset, single a init=/bin/bash pokryjí většinu situací.

Zkracuj start rušením služeb, ne přehazováním závislostí.

Kam dál