GRUB 2 - это то звено, что стоит между прошивкой (BIOS или UEFI) и ядром Linux. Если оно сломано, машина не загрузится, и никакие красивые сервисы systemd вам не помогут. В этом уроке разбираем, как GRUB 2 находит и грузит ядро, чем правится его конфиг (и почему править его руками - почти всегда ошибка), как поставить загрузчик заново после слетевшей установки Windows или ошибки в разметке, и что делать, если вы видите только мигающий курсор или приглашение grub rescue.

Как это работает
GRUB 2 (пакеты и команды в разных дистрибутивах называются по-разному: grub в Debian/Ubuntu, grub2 в RHEL/Fedora) грузится в несколько стадий. На BIOS-системах в первый сектор диска (MBR) пишется крошечный код, который умеет только найти и подгрузить следующую стадию - ядро GRUB (core.img), лежащее обычно в зазоре после MBR или в BIOS Boot Partition на GPT-дисках. На UEFI-системах все проще и надежнее: прошивка читает файл .efi (например grubx64.efi) прямо с EFI System Partition (ESP), смонтированной в /boot/efi, по записи в NVRAM.
Дальше GRUB читает свой главный файл grub.cfg. Внимание: это сгенерированный файл, его НЕ редактируют руками. На Debian/Ubuntu он лежит в /boot/grub/grub.cfg, на RHEL/Fedora исторически в /boot/grub2/grub.cfg, а на UEFI-RHEL раньше был в /boot/efi/EFI/<distro>/grub.cfg. В современных RHEL 9/10 и Fedora этот путь унифицировали через BLS (Boot Loader Specification): меню больше не зашито в grub.cfg, а собирается из отдельных файлов-сниппетов в /boot/loader/entries/, по одному на каждое ядро.
Чтобы изменить меню, вы правите ИСХОДНИКИ, а потом перегенерируете grub.cfg. Источников два: файл настроек /etc/default/grub (таймаут, дефолтное ядро, параметры командной строки ядра, тема) и набор скриптов в /etc/grub.d/ (00_header, 10_linux, 30_os-prober, 40_custom и так далее - порядок задается числовым префиксом). Скрипты при генерации запускаются, их вывод склеивается в итоговый grub.cfg. Именно поэтому ручные правки grub.cfg затираются при первом же обновлении ядра.
Параметр GRUB_CMDLINE_LINUX в /etc/default/grub - самый частый предмет редактирования: туда добавляют вещи вроде quiet splash, или, наоборот, убирают их для диагностики, прописывают resume= для гибернации, console= для последовательной консоли. Все, что вы туда впишете, попадет ядру как аргументы.
Команды и примеры
Перегенерация конфига после правки /etc/default/grub. Debian/Ubuntu:
Код: Выделить всё
update-grub
# это обертка над:
grub-mkconfig -o /boot/grub/grub.cfgКод: Выделить всё
grub2-mkconfig -o /boot/grub2/grub.cfgКод: Выделить всё
grub-install /dev/sda
update-grubКод: Выделить всё
grub2-install /dev/sda
grub2-mkconfig -o /boot/grub2/grub.cfgКод: Выделить всё
# Debian/Ubuntu
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian
# RHEL/Fedora обычно переустанавливают только efi-файл:
grub2-install --target=x86_64-efi --efi-directory=/boot/efiКод: Выделить всё
grubby --default-kernel
grubby --set-default /boot/vmlinuz-6.12.0-55.el10.x86_64
grubby --update-kernel=ALL --args="audit=0"Код: Выделить всё
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot/efi # если UEFI
for d in dev proc sys run; do mount --bind /$d /mnt/$d; done
chroot /mnt
grub-install /dev/sda && update-grub # или grub2-* в RHEL
exit- Правили grub.cfg напрямую, а после dnf/apt update ядра все откатилось - правьте /etc/default/grub и перегенерируйте.
- На BIOS дали grub-install раздел (/dev/sda1) вместо диска (/dev/sda) - загрузчик встал криво или не встал.
- Перепутали BIOS и UEFI: ставите BIOS-GRUB на машину, которая грузится через UEFI. Проверьте: каталог /sys/firmware/efi существует только на UEFI.
- Забыли смонтировать /boot/efi внутри chroot перед grub-install на UEFI - файл .efi уйдет в пустоту.
- os-prober по умолчанию отключен в свежих сборках (GRUB_DISABLE_OS_PROBER=true), и соседняя Windows не появляется в меню. Включайте осознанно.
- В RHEL 9/10 ждете меню в grub.cfg, а оно собирается из /boot/loader/entries/ через BLS - правки в grub.cfg на пункты меню не влияют.
- Откройте /etc/default/grub, увеличьте GRUB_TIMEOUT до 10 и уберите quiet из GRUB_CMDLINE_LINUX_DEFAULT.
- Перегенерируйте конфиг (update-grub или grub2-mkconfig -o ...) и перезагрузитесь - убедитесь, что меню висит 10 секунд и в логе видна загрузка ядра.
- Посмотрите список пунктов: на RHEL выполните ls /boot/loader/entries/ и grubby --info=ALL.
- Сломайте загрузчик намеренно в тестовой ВМ: затрите первый сектор - dd if=/dev/zero of=/dev/sda bs=446 count=1 (только в одноразовой ВМ!).
- Загрузитесь с live-образа, сделайте chroot по схеме из урока и восстановите GRUB через grub-install.
- Верните GRUB_TIMEOUT к разумному значению (5) и снова перегенерируйте конфиг.
- Какой файл является источником для генерации меню, а какой - результатом, и какой из них нельзя править руками?
- Чем отличается аргумент команды grub-install на BIOS-системе от UEFI-системы?
- Где в RHEL 10 физически хранятся пункты меню для разных ядер и как называется эта спецификация?
- Какие шаги нужны, чтобы восстановить загрузчик из live-образа, и зачем там bind-монтирование /dev, /proc, /sys?
- Как в Fedora/RHEL сменить ядро по умолчанию, не редактируя текстовые файлы?
- Что такое systemd-boot и в каких случаях его выбирают вместо GRUB 2?