GRUB2 — выбор kernel и rescue mode
Когда сервер загружается и вы видите на чёрном экране меню с вариантами kernel, “Advanced options for Ubuntu”, “Memory test” — это GRUB. Grand Unified Bootloader — де-факто стандартный bootloader для Linux на x86_64. Он загружает kernel, передаёт ему параметры, и (важно для админа!) даёт точку входа в rescue mode, когда обычная загрузка сломалась.
В этом уроке: что GRUB делает на каждом шаге, как редактировать его конфиг (/etc/default/grub), что такое GRUB shell и зачем уметь править kernel cmdline на лету — это спасает 4-утренние инциденты, когда сервер падает в loop восстановления.
GRUB в архитектуре загрузки
Когда вы изучали урок 13.1, мы говорили о цепочке firmware -> bootloader -> kernel. GRUB — это bootloader. На современных серверах:
- Legacy BIOS-машины. GRUB живёт в MBR (первые 512 байт диска) + дополнительные стадии в первых ~30 КБ диска. Не помещается в 512 байт сам GRUB — поэтому он разбит на стадии (stage1, stage1.5, stage2).
- UEFI-машины. GRUB живёт в ESP (EFI System Partition) как файл
/boot/efi/EFI/<distro>/grubx64.efi. Firmware загружает этот файл напрямую.
В обоих случаях после старта GRUB читает /boot/grub/grub.cfg — сгенерированный файл со всеми entries (kernel-варианты, рекавери, memory test).
Файлы конфигурации
Базовая структура файлов GRUB на Ubuntu/Debian:
/etc/default/grub # admin-edited config (источник правды для админа)
/etc/grub.d/ # скрипты, которые генерируют grub.cfg
00_header # заголовок, общие настройки
05_debian_theme # стилизация
10_linux # автогенерация entries для всех kernel
20_linux_xen
30_os-prober # entries для других OS (Windows если dual-boot)
40_custom # для custom entries
41_custom # для custom entries
/boot/grub/grub.cfg # сгенерированный config (не редактировать руками!)
Главное правило: не редактируйте /boot/grub/grub.cfg напрямую. Он перегенерируется при каждом kernel-upgrade и затрёт ваши изменения. Редактируйте /etc/default/grub и/или скрипты в /etc/grub.d/, потом sudo update-grub.
/etc/default/grub: что внутри
$ sudo cat /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR="Ubuntu"
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""
Что значит каждая опция:
GRUB_DEFAULT=0— индекс default-entry (0 = первый = самый новый kernel).GRUB_TIMEOUT=10— сколько секунд показывать меню (0 = сразу boot, -1 = ждать вечно).GRUB_TIMEOUT_STYLE=hidden— “hidden” не показывает меню, “menu” показывает.GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"— параметры kernel для нормальной загрузки.GRUB_CMDLINE_LINUX=""— параметры для ВСЕХ entries (включая recovery).
После любых изменений:
sudo update-grub # Debian/Ubuntu
# или:
sudo grub-mkconfig -o /boot/grub/grub.cfg # RHEL/Fedora/Arch
# или (UEFI с alternative configdir):
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
Kernel command line: что туда писать
GRUB_CMDLINE_LINUX_DEFAULT и GRUB_CMDLINE_LINUX — это параметры, которые GRUB передаст kernel. Kernel-cmdline — мощный инструмент.
Полезные параметры:
# Не показывать заставку, видеть все kernel-сообщения:
GRUB_CMDLINE_LINUX_DEFAULT="" # убрать quiet и splash
# Загрузка в single user mode (rescue):
single
# Загрузка с другим init (например debug shell):
init=/bin/bash
# Не активировать swap:
noswap
# Игнорировать reserved memory (если плохо считается):
mem=8G
# Отключить watchdog:
nowatchdog
# Включить kernel debug:
debug
# Для production: serial console (полезно когда нет видеовывода):
console=ttyS0,115200n8
# Ограничить число CPU (для debug):
maxcpus=1
# IOMMU включить (для passthrough):
intel_iommu=on iommu=pt
# Отключить SELinux (RHEL):
selinux=0
# Включить Magic SysRq (для аварийного восстановления):
sysrq=1
После изменения /etc/default/grub:
sudo update-grub
# Проверить:
grep '^[[:space:]]*linux' /boot/grub/grub.cfg | head -3
# Увидите: linux /boot/vmlinuz-... root=UUID=... ro quiet splash
Динамическое редактирование на boot
Самая полезная функция GRUB на практике: редактирование entry перед запуском. Сценарий: вы пришли с pager-alert, что что-то сломалось, надо запустить single-user mode — но нет времени менять config.
Шаги:
- Перезагружаете сервер.
- На GRUB меню (если оно не появилось — держите Shift при boot или нажимайте Esc).
- Стрелками выбираете нужный kernel.
- Нажимаете e — открывается редактор.
- Стрелкой вниз идёте к строке
linux /boot/vmlinuz.... - В конце строки добавляете нужный параметр, например
singleилиinit=/bin/bash. - Ctrl-X или F10 — загрузить с этими параметрами (для одного boot).
Эта правка одноразовая — следующий boot уже без неё. Это хорошо: если “single” не помог, после reboot обычная загрузка попробует снова.
Самые частые добавления для рекавери:
single # systemd запустит rescue.target -- minimal services + login
init=/bin/bash # пропустить init вообще, прямо bash как PID 1
emergency # systemd emergency.target -- даже базовых mounts нет
systemd.unit=rescue.target # systemd альтернатива single
nomodeset # без видео-driver (если экран чёрный из-за GPU)
GRUB shell — когда даже меню не появилось
Если GRUB вообще не может найти ваш kernel (например, корруптнут grub.cfg) — появится GRUB shell: grub> prompt. Это полноценный мини-shell с командами навигации по дискам.
grub> ls
(hd0) (hd0,gpt1) (hd0,gpt2) (hd0,gpt3)
grub> ls (hd0,gpt2)/
boot/ bin/ dev/ etc/ home/ lib/ ...
grub> set root=(hd0,gpt2)
grub> linux /boot/vmlinuz-6.5.0-21-generic root=/dev/sda2
grub> initrd /boot/initrd.img-6.5.0-21-generic
grub> boot
Что делаем:
lsбез аргументов — список дисков.ls (hd0,gpt2)/— список файлов в корне второго раздела первого диска.- Найдя свой /boot, устанавливаем root, загружаем kernel и initrd, делаем boot.
Это сценарий когда grub.cfg сломан. После успешного boot — chroot в систему и update-grub, grub-install.
Маппинг устройств в GRUB:
(hd0)— первый диск целиком.(hd0,gpt1)— первый раздел первого диска (GPT-схема).(hd0,msdos1)— первый primary раздел (MBR/MSDOS-схема).(cd0)— CD-ROM.
/etc/grub.d/40_custom — свои entries
Если нужно добавить custom entry в меню GRUB (например, для альтернативного kernel или ОС, которую os-prober не нашёл):
$ sudo vim /etc/grub.d/40_custom
#!/bin/sh
exec tail -n +3 $0
# Below is the actual code
menuentry "My Custom Kernel" {
set root=(hd0,gpt2)
linux /boot/vmlinuz-custom root=/dev/sda2 ro quiet
initrd /boot/initrd-custom
}
menuentry "Memtest86+" {
set root=(hd0,gpt1)
linux16 /memtest86+.bin
}
Не забудьте сделать файл executable: chmod +x /etc/grub.d/40_custom. После update-grub ваши entries появятся в grub.cfg в конце.
grub-install — переустановка bootloader
Иногда GRUB надо переустановить (после восстановления диска, изменения partition layout, dual-boot install Windows перезатёр MBR):
# BIOS-машина (на MBR-диск):
sudo grub-install /dev/sda
sudo update-grub
# UEFI-машина:
sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu
sudo update-grub
--bootloader-id — имя поддиректории в ESP (/boot/efi/EFI/<id>/) и метка в efibootmgr.
# Проверить, что попало в EFI variables:
sudo efibootmgr -v
Boot0001* ubuntu HD(1,GPT,...,800,100000)/File(\EFI\ubuntu\shimx64.efi)
Защита GRUB паролем
Для серверов в shared-environments часто хотят защитить GRUB паролем — чтобы не давать access к single-mode без admin’а:
# Сгенерировать хеш пароля:
sudo grub-mkpasswd-pbkdf2
Enter password:
Reenter password:
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.AAAA...
# Добавить в /etc/grub.d/40_custom:
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.AAAA...
sudo update-grub
Теперь редактирование entry или GRUB shell потребует пароль.
GRUB-пароль — НЕ защита от physical attacker. Кто-то с физическим доступом всегда может загрузиться с LiveCD, замаунтить ваш диск, прочитать данные. Для serious security — full disk encryption (LUKS).
Дебаг проблем GRUB
Симптом: GRUB меню не появляется.
# Принудительно показать меню:
sudo sed -i 's/GRUB_TIMEOUT_STYLE=hidden/GRUB_TIMEOUT_STYLE=menu/' /etc/default/grub
sudo sed -i 's/GRUB_TIMEOUT=0/GRUB_TIMEOUT=10/' /etc/default/grub
sudo update-grub
Симптом: “error: file ‘/boot/vmlinuz-…’ not found”.
Возможно, удалили старый kernel но он ещё в grub.cfg. Решение: sudo update-grub пересоздаст.
Симптом: после Windows install Linux исчез из меню.
Windows перезаписал MBR/UEFI boot order. Решение: загрузиться с Linux LiveUSB, chroot, grub-install, update-grub.
Симптом: GRUB rescue prompt (“grub rescue>”).
Это самый минимальный GRUB shell. Файловая система сломана или удалены критичные файлы. Команды очень ограничены, нужно вручную загружать stage2:
grub rescue> ls
(hd0) (hd0,gpt1) (hd0,gpt2)
grub rescue> set root=(hd0,gpt2)
grub rescue> set prefix=(hd0,gpt2)/boot/grub
grub rescue> insmod normal
grub rescue> normal
# Если повезло -- появится нормальный GRUB меню
После этого с LiveCD сделать chroot и grub-install, update-grub.
Попробуй сам
# 1. Посмотреть текущий config (только источник правды):
cat /etc/default/grub
# 2. Посмотреть сгенерированный grub.cfg (только информативно):
grep '^menuentry\|^[[:space:]]*linux' /boot/grub/grub.cfg | head -10
# 3. Узнать какой kernel дефолтный:
sudo grub-editenv list
# 4. (При следующем boot) показать меню принудительно:
# Подержать Shift при загрузке или нажимать Esc
# 5. Сделать показ меню постоянным:
sudo sed -i 's/GRUB_TIMEOUT_STYLE=hidden/GRUB_TIMEOUT_STYLE=menu/' /etc/default/grub
sudo update-grub
# 6. Изменить timeout на 5 секунд:
sudo sed -i 's/GRUB_TIMEOUT=10/GRUB_TIMEOUT=5/' /etc/default/grub
sudo update-grub
# 7. Что в EFI variables (только UEFI):
sudo efibootmgr -v
# 8. Сгенерировать grub-пароль (не применять, просто посмотреть):
grub-mkpasswd-pbkdf2
# Тренировка ради тренировки