Gdy serwer nie wstaje
Po tej lekcji: kursant umie wejść do trybu ratunkowego i awaryjnego, zmienić wpis w GRUB-ie na jeden start, zresetować zapomniane hasło roota na RHEL-u (rd.break) i Ubuntu (recovery mode), naprawić błąd w /etc/fstab, uruchomić fsck i wie, co zrobić po kernel panic.
Wstęp
You are in emergency mode. After logging in, type "journalctl -xb" to view
system logs, "systemctl reboot" to reboot, or "exit"
to continue bootup.
Give root password for maintenance
(or press Control-D to continue):Kolega w piątek dopisał do /etc/fstab nowy dysk. Poszedł do domu. W nocy była aktualizacja z restartem. Rano serwer stoi na tym ekranie, nie ma sieci, nie ma SSH, nic. Jest tylko konsola i Ty.
Panika jest naturalna. Ale ten ekran to nie jest koniec świata, tylko zaproszenie. System mówi: „coś mi nie pasuje, wejdź i napraw”. Dzisiaj nauczysz się z niego korzystać, a przy okazji odzyskasz zapomniane hasło roota. Bez reinstalacji, bez płakania.
Wszystko z tej lekcji ćwicz na maszynie wirtualnej. Na serio. Najlepiej zrób jej migawkę, jak w lekcji o KVM. Zepsuć rozruch jest łatwo, a ćwiczyć naprawę na serwerze produkcyjnym to jak uczyć się pływać na Titanicu.
Gdzie start może się wysypać
Przypomnienie z lekcji o starcie systemu. Rozruch to sztafeta, cztery osoby podają sobie pałeczkę:
- Firmware (BIOS albo UEFI) budzi sprzęt i szuka programu rozruchowego.
- GRUB pokazuje menu, ładuje jądro i initramfs i podaje jądru parametry.
- Jądro z initramfs startuje, ładuje sterowniki i szuka dysku z głównym systemem plików.
- systemd, kierownik zmiany, montuje dyski z
/etc/fstabi uruchamia usługi aż do celu, zwyklemulti-user.target.
Każdy z nich może upuścić pałeczkę i każdy upuszcza ją inaczej. Brak menu i czarny ekran: firmware albo GRUB. Kernel panic: jądro. Tryb awaryjny z prośbą o hasło: systemd, najczęściej przez fstab. Jak wiesz, kto upuścił, wiesz, gdzie szukać.
Tryb ratunkowy i awaryjny
W budynku są dwa rodzaje wejścia dla obsługi technicznej. Rescue, czyli tryb ratunkowy, to wejście, gdy budynek stoi, ale biura są zamknięte. Prąd jest, korytarze oświetlone, wszystkie skrzydła podłączone, tylko nikogo nie wpuszczamy. Emergency, tryb awaryjny, to wejście przez piwnicę z latarką. Działa tylko szkielet budynku, a do tego tylko do oglądania.
rescue.target | emergency.target | |
|---|---|---|
główny system plików / | zamontowany do zapisu | tylko do odczytu |
pozostałe dyski z fstab | zamontowane | niezamontowane |
| sieć, usługi | nie | nie |
| hasło roota | tak | tak |
| kiedy | coś w usługach, chcesz spokoju | fstab, uszkodzony dysk, rescue też nie wstaje |
Na działającym systemie przejdziesz do trybu ratunkowego komendą:
systemctl get-default
sudo systemctl isolate rescue.targetisolate znaczy „zatrzymaj wszystko, czego ten cel nie potrzebuje”. Przez SSH tego nie rób: sieć jest pierwszą rzeczą, która zniknie, a Ty razem z nią. Tylko z konsoli.
Częściej jednak trzeba tam wejść, kiedy system nie startuje. Wtedy cel podajesz jądru w GRUB-ie. Dokumentacja Red Hata podaje parametry systemd.unit=rescue.target i systemd.unit=emergency.target. Krócej działają też słowa rescue i emergency.
Edycja wpisu w GRUB-ie
GRUB to ochroniarz przy bramie, który ma kartkę z instrukcją dla jądra. Możesz mu tę kartkę na jeden raz przekreślić i dopisać coś od siebie.
- Uruchom ponownie maszynę.
- W menu GRUB-a ustaw się na wpisie, który chcesz uruchomić, i wciśnij
e. - Zjedź strzałkami do linijki, która zaczyna się od
linux. To jest kartka dla jądra. - Przejdź na koniec tej linijki (
EndalboCtrl+E) i dopisz parametr po spacji, na przykładsystemd.unit=rescue.target. Ctrl+Xuruchamia system z tą zmianą.
menu edycji GRUB-a z podświetloną linijką linux ... ro crashkernel=... rhgb quiet
Zmiana działa jeden raz. Po restarcie kartka wraca do oryginału. Esc w trakcie edycji wyrzuca wszystkie Twoje zmiany. Dobra rada: przy okazji skasuj z linijki rhgb quiet [RHEL] albo quiet splash [Ubuntu]. Zamiast ładnego logo zobaczysz, co system robi i na czym się zatrzymał.
[Ubuntu] Na Ubuntu menu GRUB-a jest domyślnie schowane. W pliku /etc/default/grub stoi GRUB_TIMEOUT_STYLE=hidden i GRUB_TIMEOUT=0. Żeby je zobaczyć, przytrzymaj Shift zaraz po włączeniu na maszynach z BIOS-em albo wciskaj Esc na maszynach z UEFI. Na maszynie wirtualnej trzeba mieć refleks kota.
Zmiany na stałe robisz w systemie, nie w menu:
sudo grubby --info=ALL
sudo grubby --default-kernel
sudo grubby --update-kernel=ALL --remove-args="rhgb quiet"sudo nano /etc/default/grub # np. GRUB_TIMEOUT_STYLE=menu, GRUB_TIMEOUT=5
sudo update-grubReset hasła roota na RHEL: rd.break
Zapomniałeś hasła roota, a zwykły użytkownik nie ma sudo. Na egzaminie RHCSA to klasyk, w pracy też się zdarza, zwykle na maszynie, którą ktoś postawił trzy lata temu i nie zapisał hasła nigdzie, bo „przecież zapamiętam”.
Pomysł jest taki: zatrzymujemy start, zanim system wpuści kogokolwiek do środka. Parametr rd.break mówi initramfs: „zatrzymaj się tuż przed przekazaniem pałeczki prawdziwemu systemowi i daj mi powłokę”. Prawdziwy system jest w tym momencie podłączony pod /sysroot, tylko do odczytu.
Procedura z dokumentacji RHEL 9, krok po kroku:
- Restart, w GRUB-ie
ena wpisie systemu. - Na końcu linijki
linuxdopiszrd.break. Ctrl+X. Pojawia się znak zachętyswitch_root:/#.- Dalej komendy:
mount -o remount,rw /sysroot
chroot /sysroot
passwd
touch /.autorelabel
exit
exitCo robi każda linijka:
mount -o remount,rw /sysroot— przepina prawdziwy system z „tylko do odczytu” na „do zapisu”. Bez tegopasswdnie ma gdzie zapisać nowego hasła.chroot /sysroot— wchodzisz do prawdziwego systemu, od teraz/to Twój dysk, a nie mini-system z initramfs. Jak przejście z przedsionka do budynku.passwd— nowe hasło roota.touch /.autorelabel— prośba do SELinuksa o ponowne nadanie etykiet wszystkim plikom przy następnym starcie. Dlaczego, za chwilę.- pierwszy
exitwychodzi zchroot, drugi kończy powłokę i system startuje dalej.
Po starcie SELinux przechodzi po wszystkich plikach i nadaje etykiety. Na dużym dysku to trwa i dokumentacja ostrzega, że może długo. Potem system sam się restartuje. Nie przerywaj, nie wyłączaj, idź po kawę. Po wszystkim logujesz się nowym hasłem.
Reset hasła na Ubuntu: recovery mode
Ubuntu ma gotowe menu ratunkowe, pakiet friendly-recovery.
- Pokaż menu GRUB-a (
ShiftalboEsc). - Wybierz Advanced options for Ubuntu, a potem wpis kończący się na (recovery mode).
- Pojawia się menu z opcjami:
clean(zrób wolne miejsce),dpkg(napraw zepsute pakiety),fsck(sprawdź wszystkie systemy plików),grub(zaktualizuj GRUB-a),network(włącz sieć),root(powłoka roota),system-summary(podsumowanie). - Wybierz root — Drop to root shell prompt.
Na Ubuntu konto root jest domyślnie zablokowane, więc zamiast pytania o hasło zobaczysz:
Press Enter for maintenance
(or press Control-D to continue):Enter i jesteś rootem. Dalej:
mount -o remount,rw /
passwd eryk
sync
rebootNa Ubuntu nie ma SELinuksa, więc nie ma /.autorelabel. Jest AppArmor, a on etykiet na plikach nie trzyma.
I teraz zatrzymaj się na chwilę. Właśnie zresetowałeś hasło roota bez znajomości żadnego hasła. Każdy, kto ma dostęp do konsoli, może zrobić to samo. Fizyczny dostęp do serwera to dostęp do roota. Dlatego serwerownie mają zamki, GRUB może mieć własne hasło (sudo grub2-setpassword na RHEL-u), a dyski laptopów szyfruje się. Zaszyfrowany dysk bez hasła do niego to dla złodzieja bardzo drogi przycisk do papieru.
Błąd w fstab
Wracamy do haka. Kolega dopisał dysk i zrobił literówkę w UUID. Albo dopisał dysk, który potem ktoś odpiął. systemd przy starcie czeka na urządzenie, domyślnie półtorej minuty, nie znajduje, a dysk jest wymagany, więc nie da się osiągnąć celu. Ląduje w trybie awaryjnym.
Naprawa z ekranu awaryjnego:
journalctl -xb | grep -i -E 'fstab|mount|timed out'
mount -o remount,rw /
nano /etc/fstab
systemctl daemon-reload
mount -a
findmnt --verify
systemctl reboot/ jest w trybie awaryjnym tylko do odczytu, więc przed edycją przepinasz na zapis. systemctl daemon-reload każe systemd przeczytać fstab jeszcze raz, bo systemd robi z każdej linijki własną jednostkę .mount. mount -a sprawdza, czy teraz wszystko się montuje. Cisza znaczy sukces.
A lepiej sprawdzać przed restartem, nie po. findmnt --verify to korektor dla fstab. Podsunąłem mu plik z dwoma typowymi błędami: UUID z literówką na końcu i dysk, którego nie ma:
findmnt --verify --tab-file fstab-test/mnt2
[E] unreachable on boot required source: UUID=f9e2a666-e697-45e8-86bf-1de0caf41e60
/backup
[E] unreachable on boot required target: No such file or directory
[W] unreachable source: /dev/sdb1: No such file or directory
[W] ext5 seems unsupported by the current kernel
0 parse errors, 2 errors, 4 warningsI mount -a na tym samym pliku:
mount: /mnt2: can't find UUID=f9e2a666-e697-45e8-86bf-1de0caf41e60.
mount: /backup: mount point does not exist.Zasada na całe życie: po każdej zmianie w fstab najpierw findmnt --verify i mount -a, a restart dopiero, jak oba milczą. A dla dysków, bez których serwer może żyć, na przykład z kopiami, opcja nofail, którą znasz z modułu o dyskach. Wtedy brak dysku to ostrzeżenie w dzienniku, a nie stojący serwer.
fsck przy starcie
fsck to przegląd techniczny systemu plików. Sprawdza, czy spis treści zgadza się z tym, co naprawdę leży na półkach. Szósta kolumna w fstab mówi, czy i w jakiej kolejności robić przegląd przy starcie: 1 dla /, 2 dla reszty, 0 nigdy. Przy starcie robi to usługa systemd-fsck.
Zepsujmy coś na pliku zamiast dysku. Robię system plików i kasuję mu główny superblok, czyli stronę tytułową ze spisem treści:
truncate -s 200M dysk.img
mkfs.ext4 -q -L dane dysk.img
dumpe2fs dysk.img 2>/dev/null | grep -i 'superblock at'
dd if=/dev/zero of=dysk.img bs=1024 seek=1 count=1 conv=notrunc
e2fsck -fy dysk.img
echo $? Primary superblock at 0, Group descriptors at 1-1
Backup superblock at 32768, Group descriptors at 32769-32769
e2fsck 1.47.0 (5-Feb-2023)
ext2fs_open2: Bad magic number in super-block
e2fsck: Superblock invalid, trying backup blocks...
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
dane: ***** FILE SYSTEM WAS MODIFIED *****
1ext4 trzyma zapasowe kopie superbloku, jak książka, która ma spis treści na początku i jeszcze kilka razy w środku. e2fsck sam sięgnął po zapasowy. Kod 1 znaczy „były błędy, naprawiłem”, 0 „czysto”, 4 „zostały błędy”. Jak sam nie znajdzie, podajesz mu zapasowy ręcznie: e2fsck -b 32768 /dev/sdb1.
Najważniejsza zasada: nigdy nie naprawiaj zamontowanego systemu plików. To jak remont kuchni w trakcie obiadu dla trzydziestu osób. Nowy e2fsck na szczęście sam odmówi:
/dev/loop1 is mounted.
e2fsck: Cannot continue, aborting.System plików / sprawdzasz więc przy starcie albo z płyty ratunkowej. Wymuszenie przeglądu przy najbliższym starcie: parametr jądra fsck.mode=force, a do tego fsck.repair=yes, żeby odpowiadał „tak” na pytania o naprawę.
[RHEL] Domyślny system plików RHEL-a to XFS i on działa inaczej. Przy starcie fsck.xfs nic nie robi, bo XFS po nieczystym wyłączeniu sam odtwarza dziennik przy montowaniu. Dlatego w fstab RHEL-a szósta kolumna dla XFS to 0. Naprawa ręczna, na odmontowanym:
sudo xfs_repair -n /dev/vdb1 # tylko sprawdź
sudo xfs_repair /dev/vdb1 # naprawNa zamontowanym:
xfs_repair: /dev/loop1 contains a mounted and writable filesystem
fatal error -- couldn't initialize XFS libraryKernel panic
Kernel panic to moment, w którym jądro mówi: „nie wiem, co dalej, i nie zaryzykuję zgadywania”. Zatrzymuje wszystko. Jak pilot, który przy sprzecznych odczytach przyrządów nie leci dalej na ślepo. Najsłynniejszy komunikat to:
„Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)”
Po ludzku: jądro wystartowało, ale nie umie dostać się do dysku z systemem. Najczęstsze powody po aktualizacji: brakuje initramfs dla nowego jądra albo jest uszkodzony, na przykład bo /boot się zapełnił w trakcie instalacji. Albo w linijce linux stoi zły root=.
Pierwsza pomoc: w GRUB-ie wybierz starsze jądro. Dlatego menedżer pakietów trzyma kilka wersji. Jak na starszym działa, odbudowujesz initramfs dla nowego:
# RHEL
sudo dracut -f /boot/initramfs-WERSJA.img WERSJA
# Ubuntu
sudo update-initramfs -u -k WERSJAI sprawdzasz df -h /boot, bo to częsty winowajca.
Co robi serwer po panice, mówi ustawienie kernel.panic: liczba sekund do automatycznego restartu, 0 znaczy „stój i czekaj na człowieka”.
sysctl kernel.panickernel.panic = 1Tak jest na mojej maszynie testowej, która po panice od razu się restartuje. Na zwykłej instalacji zobaczysz inną wartość.
Jak to działa pod spodem
initramfs to mały system plików w pamięci, ładowany przez GRUB-a razem z jądrem. Ma w sobie sterowniki i narzędzia potrzebne, żeby znaleźć prawdziwy dysk: LVM, RAID, szyfrowanie. Montuje prawdziwy system pod /sysroot, tylko do odczytu, a potem robi switch_root: zamienia korzeń drzewa na /sysroot i oddaje pałeczkę systemd z prawdziwego dysku. rd.break zatrzymuje ten moment tuż przed zamianą. Dlatego znak zachęty nazywa się switch_root:/#.
A SELinux? Każdy plik na RHEL-u ma etykietę, na przykład /etc/shadow ma shadow_t. W initramfs polityka SELinuksa nie jest jeszcze załadowana. passwd zapisuje hasło, tworząc nowy plik shadow i podmieniając stary. Nowy plik nie dostaje żadnej poprawnej etykiety. Po starcie SELinux w trybie enforcing patrzy na plik bez etykiety i nie pozwala programom logowania go czytać. Hasło zmienione, a zalogować się nie da. /.autorelabel każe przy starcie nadać etykiety wszystkim plikom od nowa, według polityki.
Ściąga flag
| Komenda | Flaga | Co robi |
|---|---|---|
| GRUB | e, potem Ctrl+X | edycja wpisu na jeden start, uruchomienie |
| parametr jądra | systemd.unit=rescue.target | tryb ratunkowy |
| parametr jądra | systemd.unit=emergency.target | tryb awaryjny |
| parametr jądra | rd.break | zatrzymanie w initramfs przed switch_root |
| parametr jądra | fsck.mode=force | wymuszenie fsck przy starcie |
systemctl | isolate rescue.target | przejście do trybu ratunkowego z konsoli |
systemctl | get-default / set-default | domyślny cel startu |
mount | -o remount,rw /sysroot | przepięcie na zapis |
findmnt | --verify | sprawdzenie /etc/fstab |
e2fsck | -f -y / -n / -b 32768 | wymuś i napraw / tylko sprawdź / zapasowy superblok |
xfs_repair | -n | sprawdzenie XFS bez zmian |
grubby | --update-kernel=ALL --args= / --remove-args= | stała zmiana parametrów [RHEL] |
update-grub | przebudowa konfiguracji GRUB-a [Ubuntu] | |
dracut / update-initramfs | -f / -u -k WERSJA | odbudowa initramfs |
⚠ Typowy błąd
Jesteś w switch_root:/#, emocje, pośpiech. chroot /sysroot, passwd, wpisujesz nowe hasło dwa razy i:
passwd: Authentication token manipulation error
passwd: password unchangedBrzmi jak atak hakerów, a to zwykły zapomniany mount -o remount,rw /sysroot. Dysk jest tylko do odczytu, więc passwd nie może zapisać pliku shadow. Odtworzyłem ten komunikat, montując /etc tylko do odczytu, i jest dokładnie taki. Naprawa: exit z chroot, przepięcie na zapis, jeszcze raz chroot i passwd.
Drugi wariant tego samego dramatu: hasło zmienione, restart, a logowanie dalej mówi „Login incorrect”. Zapomniany touch /.autorelabel. Plik shadow stracił etykietę i SELinux nie daje go czytać. Powtarzasz rd.break, tym razem z touch /.autorelabel, i czekasz na przeetykietowanie.
✎ Zadanie
Na maszynie wirtualnej, po zrobieniu migawki:
- Wejdź do trybu ratunkowego przez edycję wpisu w GRUB-ie i sprawdź
systemctl list-units --type=mount. - Zresetuj hasło roota: na RHEL-u, Rocky albo Almie przez
rd.break, na Ubuntu przez recovery mode. Zaloguj się nowym hasłem. - Dopisz do
/etc/fstablinijkę z nieistniejącym UUID, sprawdźfindmnt --verify, zrestartuj i napraw serwer z trybu awaryjnego.
Pokaż rozwiązanie
Część pierwsza, tryb ratunkowy. W GRUB-ie e, na koniec linijki linux dopisujesz systemd.unit=rescue.target, Ctrl+X, hasło roota. I:
systemctl list-units --type=mountWidzisz zamontowane /, /boot i resztę z fstab. W trybie ratunkowym budynek stoi z zapalonym światłem. Gdybyś to samo zrobił w emergency.target, lista byłaby krótsza, a / tylko do odczytu.
Część druga, hasło roota. [RHEL] rd.break, potem:
mount -o remount,rw /sysroot
chroot /sysroot
passwd
touch /.autorelabel
exit
exit[Ubuntu] Advanced options, recovery mode, root, Enter, mount -o remount,rw /, passwd eryk, reboot. Jeśli na RHEL-u po restarcie widzisz długie przeetykietowywanie, a potem drugi restart, to wszystko działa jak trzeba.
Część trzecia, zepsuty fstab. Przed restartem korektor już krzyczał:
[E] unreachable on boot required source: UUID=f9e2a666-e697-45e8-86bf-1de0caf41e60Po restarcie tryb awaryjny, hasło roota, i naprawa:
mount -o remount,rw /
nano /etc/fstab # usuń lub popraw linijkę, albo dopisz nofail
systemctl daemon-reload
mount -a && findmnt --verify
systemctl rebootJeśli zrobiłeś wcześniej migawkę maszyny, gratulacje: masz też plan B. Ten odruch przyda się dziś bardziej niż kiedykolwiek.
Co dalej
To był rozruch. Ale większość awarii zdarza się na serwerze, który wstał: jest wolny, kończy mu się pamięć, dysk albo i-węzły, usługa nie chce startować, SSH milczy, strona nie działa. W następnej lekcji metoda na każdą taką awarię, krok po kroku, i to, co robi się po niej: zgłoszenie, zmiana, dokumentacja i raport po awarii.