Рано или поздно стенд перестаёт грузиться: кто-то поправил fstab и опечатался в UUID, обновление снесло запись в загрузчике, диск переразметили и GRUB потерял своё ядро. В этом уроке разбираем три уровня глубины починки: одноразовый аварийный таргет через параметр ядра, ремонт уже частично поднятой системы и полное восстановление с live-носителя через chroot. Заодно поймём, чем UEFI отличается от BIOS при переустановке загрузчика - это место, где чаще всего ломают руки.

Как это работает
Загрузка идёт по цепочке: прошивка (BIOS или UEFI) находит загрузчик, GRUB разворачивает ядро и initramfs, ядро монтирует корень и передаёт управление systemd как PID 1. systemd доводит систему до таргета по умолчанию (обычно multi-user.target или graphical.target). Сломаться может любое звено, и для каждого есть точка вмешательства.
Если система в принципе грузится, но падает на каком-то сервисе, нам хватит сокращённого таргета. rescue.target поднимает корень для чтения и записи, запускает базовые юниты и udev, спрашивает пароль root и даёт shell - это аналог старого single-user. emergency.target ещё жёстче: корень примонтирован только для чтения, не запущено почти ничего, даже local-fs.target. Туда падаешь, когда сломан fstab и обычное монтирование не проходит.
Задать таргет на один раз можно прямо из GRUB. В меню жмём e, находим строку, начинающуюся с linux (на части UEFI-сборок - linuxefi), и дописываем в конец systemd.unit=rescue.target или systemd.unit=emergency.target, затем Ctrl-x для загрузки. Это разовый трюк, следующая перезагрузка снова идёт в дефолтный таргет. Полезные соседи: rd.break роняет нас в shell ещё внутри initramfs (до switch_root), а init=/bin/bash целиком минует systemd.
initramfs - это маленький временный корень в оперативке. Его задача - подгрузить драйверы дискового контроллера, собрать RAID, развернуть LVM, открыть LUKS и только потом смонтировать настоящий корень. Если после смены железа или шифрования система виснет на этапе поиска корня, почти всегда виноват устаревший initramfs, и его надо пересобрать. В Debian/Ubuntu это update-initramfs, в RHEL/Fedora - dracut.
chroot нужен, когда система не грузится вообще. Мы стартуем с live-образа, монтируем разделы установленной системы в каталог, прокидываем туда живые псевдо-ФС ядра (/proc, /sys, /dev) и делаем chroot. Внутри получаем окружение, где все пути и команды ведут себя так, будто система загружена нормально - можно править конфиги, пересобирать initramfs и переустанавливать загрузчик.
Команды и примеры
Монтируем целевую систему и заходим в chroot (предположим, корень на /dev/sda2, EFI-раздел на /dev/sda1):
Код: Выделить всё
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot/efi # только для UEFI
for d in /dev /proc /sys /run; do mount --rbind $d /mnt$d; done
chroot /mnt /bin/bash
Код: Выделить всё
# Debian / Ubuntu
update-initramfs -u -k all
# RHEL / Fedora
dracut --force --regenerate-all
UEFI (целевой диск /dev/sda, ESP смонтирован в /boot/efi):
Код: Выделить всё
# Debian / Ubuntu
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian
update-grub
# RHEL / Fedora
grub2-install --target=x86_64-efi --efi-directory=/boot/efi
grub2-mkconfig -o /boot/grub2/grub.cfg
Код: Выделить всё
# Debian / Ubuntu
grub-install /dev/sda
update-grub
# RHEL / Fedora
grub2-install /dev/sda
grub2-mkconfig -o /boot/grub2/grub.cfg
Код: Выделить всё
mount -o remount,rw /
blkid # сверяем реальные UUID
nano /etc/fstab
systemctl daemon-reload # перечитать units, сгенерированные из fstab
mount -a # проверить без перезагрузки
- Забыли прокинуть /proc, /sys, /dev перед chroot - grub-install и dracut ругаются на отсутствие устройств или собирают мусор.
- В UEFI пытаются записать GRUB в MBR командой grub-install /dev/sda. В UEFI загрузчик ставится в ESP и регистрируется в NVRAM через efibootmgr, а не в загрузочный сектор.
- На RHEL/Fedora с UEFI файл /boot/efi/EFI/redhat/grub.cfg - это заглушка. Перегенерировать конфиг надо в /boot/grub2/grub.cfg, иначе после grub2-mkconfig по неверному пути меняется не то.
- RHEL 10 использует BLS: записи лежат отдельными файлами в /boot/loader/entries/, а параметры ядра правятся через grubby, а не руками в grub.cfg.
- В fstab ставят noauto или забывают nofail на необязательном разделе - и эта строка валит весь boot в emergency, хотя проблема в одном диске.
- Пересобрали initramfs не для того ядра. update-initramfs -u без -k all и dracut без --regenerate-all обновляют только текущее, а грузится другое.
- Перепутали разовый параметр ядра с постоянным: правка в GRUB через e живёт до перезагрузки, для постоянной нужен /etc/default/grub и пересборка.
- Шаг 1. На тестовой ВМ в меню GRUB нажмите e, допишите systemd.unit=rescue.target, загрузитесь, введите пароль root и убедитесь, что вы в rescue-shell (systemctl get-default покажет прежний дефолт).
- Шаг 2. Намеренно сломайте /etc/fstab: добавьте строку с несуществующим UUID и опцией без nofail. Перезагрузитесь и поймайте падение в emergency.target.
- Шаг 3. В emergency перемонтируйте корень на запись, исправьте fstab, выполните mount -a без ошибок и перезагрузитесь в норму.
- Шаг 4. Загрузитесь с live-ISO, смонтируйте разделы установленной системы, прокиньте псевдо-ФС и войдите в chroot.
- Шаг 5. Пересоберите initramfs (update-initramfs -u -k all или dracut --force --regenerate-all) и переустановите GRUB правильной для вашего режима командой.
- Шаг 6. Выйдите из chroot, размонтируйте всё в обратном порядке и проверьте, что система грузится самостоятельно.
- Чем отличается состояние системы в rescue.target от emergency.target и в каком из них корень монтируется только для чтения?
- Какой параметр ядра дать в GRUB, чтобы один раз загрузиться в аварийный таргет, и почему эта правка не сохраняется?
- Зачем перед chroot монтировать /proc, /sys и /dev, и что сломается, если этого не сделать?
- Почему в UEFI нельзя восстанавливать загрузчик командой grub-install /dev/sda, и куда он ставится на самом деле?
- Какой командой пересобрать initramfs для всех установленных ядер в Debian и в Fedora?
- Что такое заглушка grub.cfg в EFI-каталоге RHEL и по какому пути на самом деле генерируется рабочий конфиг?