Привет, Хабр!
Мы, сервисные инженеры, сталкиваемся с GRUB2 ежедневно. А вот когда стало любопытно посмотреть на загрузчик комплексно, то в интернете и в учебнике Linux нашли лишь несколько команд: как заново проинсталлировать загрузчик и обновить текущую конфигурацию. «А почему так мало?», — была наша первая мысль. Решили восполнить пробел — так появилась эта статья. А для иллюстрации попросили нейросетку изобразить, «как выглядят эпичные проблемы с GRUB» -- вот что вышло.
Что такое загрузчик (bootloader)?
Это самая первая запускающаяся программа. Ее цель — загрузить и передать управление ядру. Оно уже завершает инициализацию и запускает операционную систему (ОС).
Можно ли обойтись без загрузчика?
Совсем без него обойтись можно, но это потребует ряд подготовительных шагов:
убедиться, что есть UEFI;
пересобрать ядро с CONFIG_EFI_STUB, если этот параметр не включен;
проверить, чтобы ядро было выше версии 3.1;
ответить на вопрос: «Ради чего вы хотите потратить приличное количество времени на это?»
Если загрузчик в вашей системе «съедает» слишком много времени (разница с перечисленными выше операциями составляет 2-3 секунды), то вам придется отказаться от него и обратить внимание на другие статьи.
Какой загрузчик использовать?
В теории у нас достаточно большой выбор загрузочных программ, но на практике многие производители используют какую-то одну. Переход на другой загрузчик можно произвести позже. Если вам любопытно, то большая сравнительная таблица доступна здесь: https://en.wikipedia.org/wiki/Comparison_of_bootloaders. Но нам ближе всего GRUB/GRUB2 по ряду причин:
Он универсален и отрабатывает, по cути, все сценарии.
Он интерактивен.
Он «понимает» файловые системы.
Большинство инженеров умеют с ним работать.
Этот загрузчик используется по умолчанию для RHEL и подобных ему дистрибутивов. «Кровавый Enterprise» душит креатив, но что поделать.
Мы пишем GRUB/GRUB2, потому как обе версии продолжают существовать, и они немного отличаются. Когда появилась вторая версия этого загрузчика, пользователи были не очень довольны некоторыми изменениями. Так, в GRUB2 стало заметно сложнее что-то прописывать руками, например, в том же интерактивном режиме. Изменился подход производителя к созданию меню, ибо «нечего лазить в настройку руками» J А теперь сравним для примера секции, отвечающие за загрузку ОС.
GRUB:
title Red Hat Enterprise Linux 6 (2.6.32-573.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-573.el6.x86_64 ro root=/dev/mapper/vg_rhel6-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 rd_LVM_LV=vg_rhel6/lv_swap crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_LVM_LV=vg_rhel6/lv_root rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-573.el6.x86_64.img
GRUB2:
menuentry 'CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-53a77eb0-927d-45ab-a110-1f00713931db' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 eabdf552-63da-4489-a0db-6a0cdde095b8
else
search --no-floppy --fs-uuid --set=root eabdf552-63da-4489-a0db-6a0cdde095b8
fi
linuxefi /vmlinuz-3.10.0-1160.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet
initrdefi /initramfs-3.10.0-1160.el7.x86_64.img
}
Что ж, со временем все привыкли :(
Звучит очень просто, но можно поподробнее о процессе загрузки?
Начнем с Basic Input Output System (BIOS). После включения питания сервера BIOS принимает управление инициализацией периферического оборудования, выполняет Power on Self Test (POST) и в конце концов переходит к чтению устройства, указанного как загрузочное. Мы не будем погружаться в прерывания BIOS, чтобы не усложнять понимание предмета, и начнем уже с Этапа # 1 (в оригинале «stage» - мы перевели это как этап, а не уровень).
На загрузочном устройстве записан Master Boot Record (MBR) — данные, необходимые для загрузки операционной системы. MBR занимают всего 512 байт. С учетом того, что последние 66 байт зарезервированы под таблицу размещения разделов (Partition Table), для загрузчика остается 446 байт (boot.img). В этот объем трудно поместить что-то сложное и самодостаточное, его задача — найти и запустить уже полноценный загрузчик. Давайте посмотрим, как Этап #1 выглядит на диске. Возьмем пустой диск.
[root@oel78 ~]# dd if=/dev/sde bs=512 count=1 | hexdump -C
[root@oel78 ~]# cat /tmp/header |hexdump -C
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000200
Создадим там одну партицию:
Hidden text
[root@oel78 ~]# fdisk /dev/sde
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0x4abaf638.
Command (m for help): p
Disk /dev/sde: 27.9 GB, 27917287424 bytes, 54525952 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x4abaf638
Device Boot Start End Blocks Id System
Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-54525951, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-54525951, default 54525951): +1G
Partition 1 of type Linux and of size 1 GiB is set
Command (m for help): p
Disk /dev/sde: 27.9 GB, 27917287424 bytes, 54525952 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x4abaf638
Device Boot Start End Blocks Id System
/dev/sde1 2048 2099199 1048576 83 Linux
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
Устанавливаем загрузчик. Важно указать весь диск, а не партицию:
Hidden text
[root@oel78 ~]# grub2-install /dev/sde
Installing for i386-pc platform.
Installation finished. No error reported.
[root@oel78 ~]# file -s /dev/sde
/dev/sde: x86 boot sector; partition 1: ID=0x83, starthead 0, startsector 2048, 2097152 sectors, extended partition table (last)\011, code offset 0x63
[root@oel78 ~]# dd if=/dev/sde of=/tmp/header-mbr |hexdump -C
00000000 eb 63 90 00 00 00 00 00 00 00 00 00 00 00 00 00 |.c..............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000050 00 00 00 00 00 00 00 00 00 00 00 80 01 00 00 00 |................|
00000060 00 00 00 00 ff fa 90 90 f6 c2 80 74 05 f6 c2 70 |...........t...p|
00000070 74 02 b2 80 ea 79 7c 00 00 31 c0 8e d8 8e d0 bc |t....y|..1......|
00000080 00 20 fb a0 64 7c 3c ff 74 02 88 c2 52 be 05 7c |. ..d|<.t...R..||
00000090 b4 41 bb aa 55 cd 13 5a 52 72 3d 81 fb 55 aa 75 |.A..U..ZRr=..U.u|
000000a0 37 83 e1 01 74 32 31 c0 89 44 04 40 88 44 ff 89 |7...t21..D.@.D..|
000000b0 44 02 c7 04 10 00 66 8b 1e 5c 7c 66 89 5c 08 66 |D.....f..\|f.\.f|
000000c0 8b 1e 60 7c 66 89 5c 0c c7 44 06 00 70 b4 42 cd |..`|f.\..D..p.B.|
000000d0 13 72 05 bb 00 70 eb 76 b4 08 cd 13 73 0d 5a 84 |.r...p.v....s.Z.|
000000e0 d2 0f 83 de 00 be 85 7d e9 82 00 66 0f b6 c6 88 |.......}...f....|
000000f0 64 ff 40 66 89 44 04 0f b6 d1 c1 e2 02 88 e8 88 |d.@f.D..........|
00000100 f4 40 89 44 08 0f b6 c2 c0 e8 02 66 89 04 66 a1 |.@.D.......f..f.|
00000110 60 7c 66 09 c0 75 4e 66 a1 5c 7c 66 31 d2 66 f7 |`|f..uNf.\|f1.f.|
00000120 34 88 d1 31 d2 66 f7 74 04 3b 44 08 7d 37 fe c1 |4..1.f.t.;D.}7..|
00000130 88 c5 30 c0 c1 e8 02 08 c1 88 d0 5a 88 c6 bb 00 |..0........Z....|
00000140 70 8e c3 31 db b8 01 02 cd 13 72 1e 8c c3 60 1e |p..1......r...`.|
00000150 b9 00 01 8e db 31 f6 bf 00 80 8e c6 fc f3 a5 1f |.....1..........|
00000160 61 ff 26 5a 7c be 80 7d eb 03 be 8f 7d e8 34 00 |a.&Z|..}....}.4.|
00000170 be 94 7d e8 2e 00 cd 18 eb fe 47 52 55 42 20 00 |..}.......GRUB .|
00000180 47 65 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 |Geom.Hard Disk.R|
00000190 65 61 64 00 20 45 72 72 6f 72 0d 0a 00 bb 01 00 |ead. Error......|
000001a0 b4 0e cd 10 ac 3c 00 75 f4 c3 00 00 00 00 00 00 |.....<.u........|
000001b0 00 00 00 00 00 00 00 00 38 f6 ba 4a 00 00 00 00 |........8..J....|
000001c0 01 01 83 3f 20 00 00 08 00 00 00 00 20 00 00 00 |...? ....... ...|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000200
Как вы видите, “Этап #1” действительно очень маленький.
Этап 1.5 GRUB’а должен находиться в пространстве между MBR и первой партицией. Этот участок исторически оставался нетронутым по техническим причинам. Первая партиция на диске начинается с 63-го сектора. Если нулевой сектор занят MBR, то у нас остается 62 сектора по 512 байт, что в сумме дает нам 31 744 байта. Здесь хранится core.img, являющийся тем самым этапом 1.5 GRUB. Его задача — загрузить драйвер файловой системы для работы со вторым этапом, расположенным в /boot. Посмотреть на Этап #1,5 сложнее, так как там находится просто код драйверов.
Примечание:
Если вы заметили, при создании партиции первым был 2048 сектор, а не 63-й:
Partition number (1-4, default 1): 1
First sector (2048-54525951, default 2048):
Using default value 2048
Это избыточно и уходит корнями в работу fdisk и его неудержимое желание выравнивать границы по “трекам” (http://jdebp.info./FGA/disc-partition-alignment.html).
Что делать, если у нас не MBR, а GPT?
Хороший вопрос, но давайте добавим сюда еще и UEFI, чтобы «два раза не вставать». Схема GPT пришла на смену MBR и в основном используется совместно с EFI/UEFI (в свою очередь, заменил BIOS), но также возможно использование и с BIOS. Данные в ней размещаются согласно картинке:
Давайте посмотрим, как выглядит работа с GPT стандартными утилитами:
Hidden text
[root@oel78 ~]# gdisk /dev/sdf
GPT fdisk (gdisk) version 0.8.10
Partition table scan:
MBR: not present
BSD: not present
APM: not present
GPT: not present
Creating new GPT entries.
Command (? for help): p
Disk /dev/sdf: 2097152 sectors, 1024.0 MiB
Logical sector size: 512 bytes
Disk identifier (GUID): B4B6ADC2-581E-4AC7-BED9-A1FDBE8E0EB7
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 2097118
Partitions will be aligned on 2048-sector boundaries
Total free space is 2097085 sectors (1024.0 MiB)
Number Start (sector) End (sector) Size Code Name
Command (? for help): n
Partition number (1-128, default 1):
First sector (34-2097118, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-2097118, default = 2097118) or {+-}size{KMGTP}: +500M
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'
Command (? for help): p
Disk /dev/sdf: 2097152 sectors, 1024.0 MiB
Logical sector size: 512 bytes
Disk identifier (GUID): B4B6ADC2-581E-4AC7-BED9-A1FDBE8E0EB7
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 2097118
Partitions will be aligned on 2048-sector boundaries
Total free space is 1073085 sectors (524.0 MiB)
Number Start (sector) End (sector) Size Code Name
1 2048 1026047 500.0 MiB 8300 Linux filesystem
Command (? for help): w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to /dev/sdf.
The operation has completed successfully.
При повторном использовании gdisk у нас уже будут и Protective MBR, и GPT:
[root@oel78 ~]# gdisk /dev/sdf
GPT fdisk (gdisk) version 0.8.10
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Command (? for help):
Давайте посмотрим на партиции:
Hidden text
Command (? for help): i
Using 1
Partition GUID code: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 (Linux filesystem)
Partition unique GUID: 00952D54-85EB-464A-A288-1B81C5F55D5C
First sector: 2048 (at 1024.0 KiB)
Last sector: 1026047 (at 501.0 MiB)
Partition size: 1024000 sectors (500.0 MiB)
Attribute flags: 0000000000000000
Partition name: 'Linux filesystem'
Command (? for help):
[root@oel78 ~]# dd if=/dev/sdf of=/tmp/header-sdf bs=512 count=3
[root@oel78 ~]# cat /tmp/header-sdf | hexdump -C
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001c0 02 00 ee 05 e1 f3 01 00 00 00 ff ff 1f 00 00 00 |................|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
00000210 54 d3 27 b6 00 00 00 00 01 00 00 00 00 00 00 00 |T.'.............|
00000220 ff ff 1f 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
00000230 de ff 1f 00 00 00 00 00 c2 ad b6 b4 1e 58 c7 4a |.............X.J|
00000240 be d9 a1 fd be 8e 0e b7 02 00 00 00 00 00 00 00 |................|
00000250 80 00 00 00 80 00 00 00 8d 24 88 fa 00 00 00 00 |.........$......|
00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000400 af 3d c6 0f 83 84 72 47 8e 79 3d 69 d8 47 7d e4 |.=....rG.y=i.G}.|
00000410 54 2d 95 00 eb 85 4a 46 a2 88 1b 81 c5 f5 5d 5c |T-....JF......]\|
00000420 00 08 00 00 00 00 00 00 ff a7 0f 00 00 00 00 00 |................|
00000430 00 00 00 00 00 00 00 00 4c 00 69 00 6e 00 75 00 |........L.i.n.u.|
00000440 78 00 20 00 66 00 69 00 6c 00 65 00 73 00 79 00 |x. .f.i.l.e.s.y.|
00000450 73 00 74 00 65 00 6d 00 00 00 00 00 00 00 00 00 |s.t.e.m.........|
00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
[root@oel78 ~]# grub2-install /dev/sdf
Installing for i386-pc platform.
grub2-install: warning: this GPT partition label contains no BIOS Boot Partition; embedding won't be possible.
grub2-install: error: embedding is not possible, but this is required for cross-disk install.
[root@oel78 ~]# gdisk /dev/sdf
GPT fdisk (gdisk) version 0.8.10
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Command (? for help): ?
b back up GPT data to a file
c change a partition's name
d delete a partition
i show detailed information on a partition
l list known partition types
n add a new partition
o create a new empty GUID partition table (GPT)
p print the partition table
q quit without saving changes
r recovery and transformation options (experts only)
s sort partitions
t change a partition's type code
v verify disk
w write table to disk and exit
x extra functionality (experts only)
? print this menu
Command (? for help): n
Partition number (2-128, default 2):
First sector (34-2097118, default = 1026048) or {+-}size{KMGTP}:
Last sector (1026048-2097118, default = 2097118) or {+-}size{KMGTP}: +200M
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'
Command (? for help):
Command (? for help): p
Disk /dev/sdf: 2097152 sectors, 1024.0 MiB
Logical sector size: 512 bytes
Disk identifier (GUID): B4B6ADC2-581E-4AC7-BED9-A1FDBE8E0EB7
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 2097118
Partitions will be aligned on 2048-sector boundaries
Total free space is 663485 sectors (324.0 MiB)
Number Start (sector) End (sector) Size Code Name
1 2048 1026047 500.0 MiB 8300 Linux filesystem
2 1026048 1435647 200.0 MiB 8300 Linux filesystem
Command (? for help): 2
b back up GPT data to a file
c change a partition's name
d delete a partition
i show detailed information on a partition
l list known partition types
n add a new partition
o create a new empty GUID partition table (GPT)
p print the partition table
q quit without saving changes
r recovery and transformation options (experts only)
s sort partitions
t change a partition's type code
v verify disk
w write table to disk and exit
x extra functionality (experts only)
? print this menu
Command (? for help): t
Partition number (1-2): 2
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): ef02
Changed type of partition to 'BIOS boot partition'
Command (? for help): w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to /dev/sdf.
The operation has completed successfully
Теперь у нас получается инсталлировать загрузчик:
Hidden text
[root@oel78 ~]# grub2-install /dev/sdf
Installing for i386-pc platform.
Installation finished. No error reported.
[root@oel78 ~]# cat /tmp/header-sdf-2 | hexdump -C
00000000 eb 63 90 00 00 00 00 00 00 00 00 00 00 00 00 00 |.c..............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000050 00 00 00 00 00 00 00 00 00 00 00 80 00 a8 0f 00 |................|
00000060 00 00 00 00 ff fa 90 90 f6 c2 80 74 05 f6 c2 70 |...........t...p|
00000070 74 02 b2 80 ea 79 7c 00 00 31 c0 8e d8 8e d0 bc |t....y|..1......|
00000080 00 20 fb a0 64 7c 3c ff 74 02 88 c2 52 be 05 7c |. ..d|<.t...R..||
00000090 b4 41 bb aa 55 cd 13 5a 52 72 3d 81 fb 55 aa 75 |.A..U..ZRr=..U.u|
000000a0 37 83 e1 01 74 32 31 c0 89 44 04 40 88 44 ff 89 |7...t21..D.@.D..|
000000b0 44 02 c7 04 10 00 66 8b 1e 5c 7c 66 89 5c 08 66 |D.....f..\|f.\.f|
000000c0 8b 1e 60 7c 66 89 5c 0c c7 44 06 00 70 b4 42 cd |..`|f.\..D..p.B.|
000000d0 13 72 05 bb 00 70 eb 76 b4 08 cd 13 73 0d 5a 84 |.r...p.v....s.Z.|
000000e0 d2 0f 83 de 00 be 85 7d e9 82 00 66 0f b6 c6 88 |.......}...f....|
000000f0 64 ff 40 66 89 44 04 0f b6 d1 c1 e2 02 88 e8 88 |d.@f.D..........|
00000100 f4 40 89 44 08 0f b6 c2 c0 e8 02 66 89 04 66 a1 |.@.D.......f..f.|
00000110 60 7c 66 09 c0 75 4e 66 a1 5c 7c 66 31 d2 66 f7 |`|f..uNf.\|f1.f.|
00000120 34 88 d1 31 d2 66 f7 74 04 3b 44 08 7d 37 fe c1 |4..1.f.t.;D.}7..|
00000130 88 c5 30 c0 c1 e8 02 08 c1 88 d0 5a 88 c6 bb 00 |..0........Z....|
00000140 70 8e c3 31 db b8 01 02 cd 13 72 1e 8c c3 60 1e |p..1......r...`.|
00000150 b9 00 01 8e db 31 f6 bf 00 80 8e c6 fc f3 a5 1f |.....1..........|
00000160 61 ff 26 5a 7c be 80 7d eb 03 be 8f 7d e8 34 00 |a.&Z|..}....}.4.|
00000170 be 94 7d e8 2e 00 cd 18 eb fe 47 52 55 42 20 00 |..}.......GRUB .|
00000180 47 65 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 |Geom.Hard Disk.R|
00000190 65 61 64 00 20 45 72 72 6f 72 0d 0a 00 bb 01 00 |ead. Error......|
000001a0 b4 0e cd 10 ac 3c 00 75 f4 c3 00 00 00 00 00 00 |.....<.u........|
000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001c0 02 00 ee 05 e1 f3 01 00 00 00 ff ff 1f 00 00 00 |................|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
00000210 25 38 90 a1 00 00 00 00 01 00 00 00 00 00 00 00 |%8..............|
00000220 ff ff 1f 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
00000230 de ff 1f 00 00 00 00 00 c2 ad b6 b4 1e 58 c7 4a |.............X.J|
00000240 be d9 a1 fd be 8e 0e b7 02 00 00 00 00 00 00 00 |................|
00000250 80 00 00 00 80 00 00 00 66 63 9c 9a 00 00 00 00 |........fc......|
00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000400 af 3d c6 0f 83 84 72 47 8e 79 3d 69 d8 47 7d e4 |.=....rG.y=i.G}.|
00000410 54 2d 95 00 eb 85 4a 46 a2 88 1b 81 c5 f5 5d 5c |T-....JF......]\|
00000420 00 08 00 00 00 00 00 00 ff a7 0f 00 00 00 00 00 |................|
00000430 00 00 00 00 00 00 00 00 4c 00 69 00 6e 00 75 00 |........L.i.n.u.|
00000440 78 00 20 00 66 00 69 00 6c 00 65 00 73 00 79 00 |x. .f.i.l.e.s.y.|
00000450 73 00 74 00 65 00 6d 00 00 00 00 00 00 00 00 00 |s.t.e.m.........|
00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000480 48 61 68 21 49 64 6f 6e 74 4e 65 65 64 45 46 49 |Hah!IdontNeedEFI|
00000490 8a 24 28 d6 d9 01 20 49 8a 8e 48 2c d9 ab 9a bb |.$(... I..H,....|
000004a0 00 a8 0f 00 00 00 00 00 ff e7 15 00 00 00 00 00 |................|
000004b0 00 00 00 00 00 00 00 00 42 00 49 00 4f 00 53 00 |........B.I.O.S.|
000004c0 20 00 62 00 6f 00 6f 00 74 00 20 00 70 00 61 00 | .b.o.o.t. .p.a.|
000004d0 72 00 74 00 69 00 74 00 69 00 6f 00 6e 00 00 00 |r.t.i.t.i.o.n...|
000004e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000600
Немного конфигураций
По сути, все возможные конфигурации можно описать следующим образом:
· BIOS и MBR.
· BIOS и GPT.
· EFI и MBR.
· EFI и GPT.
BIOS и MBR. Это самая привычная и традиционная конфигурация, описанная ранее.
BIOS и GPT. В этом варианте у нас также первый этап загрузки расположен в MBR (что для GPT известно как protective MBR — своеобразная «метка», призванная защитить диск от приложений, не умеющих работать с GPT). Дальше GRUB использует BIOS Boot Partition, имеющую GPT-метку 21686148-6449-6E6F-744E. Дополнительные файлы по-прежнему находятся в директории /boot/grub так же, как и в комбинации BIOS и MBR.
EFI и MBR. В этой конфигурации первый этап (GRUB EFI — бинарный файл) расположен в EFI System Partition (ESP; тип 0xEF на MBR диске). Данный файл может называться как угодно, но обычно используется grubx64.efi в поддиректории /boot/efi/EFI/redhat/.
EFI и GPT. Данная конфигурация, по сути, аналогична предыдущей, за исключением того, что у ESP тип кода выглядит так: C12A7328-F81F-11D2-BA4B-00A0C93EC93B. Сейчас это самое распространенное сочетание.
Как работать с GRUB2
GRUB2 самостоятельно определяет имеющиеся ядра, файлы initramfs в /boot/ и создает для них записи в меню загрузчика. Это происходит либо автоматически после установки новой версии ядра, либо выполняется вручную командой grub2-mkconfig.
Например, было:
Hidden text
# grep -A 10 "menuentry 'CentOS" grub.cfg
menuentry 'CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-53a77eb0-927d-45ab-a110-1f00713931db' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 eabdf552-63da-4489-a0db-6a0cdde095b8
else
search --no-floppy --fs-uuid --set=root eabdf552-63da-4489-a0db-6a0cdde095b8
--
menuentry 'CentOS Linux (0-rescue-f1e78ff605dd47a3bc0839d240d643c6) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-f1e78ff605dd47a3bc0839d240d643c6-advanced-53a77eb0-927d-45ab-a110-1f00713931db' {
load_video
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 eabdf552-63da-4489-a0db-6a0cdde095b8
else
search --no-floppy --fs-uuid --set=root eabdf552-63da-4489-a0db-6a0cdde095b8
fi
Устанавливаем новое ядро:
Hidden text
[root@server-centos centos]# yum update kernel
Loaded plugins: fastestmirror, langpacks, product-id, search-disabled-repos, subscription-manager, versionlock
This system is not registered with an entitlement server. You can use subscription-manager to register.
Loading mirror speeds from cached hostfile
* base: mirror.yandex.ru
* elrepo: lon.mirror.rackspace.com
* elrepo-extras: lon.mirror.rackspace.com
* elrepo-kernel: lon.mirror.rackspace.com
* elrepo-testing: lon.mirror.rackspace.com
* epel: mirror.cloudhosting.lv
* extras: mirror.yandex.ru
* updates: mirror.hyperdedic.ru
Resolving Dependencies
--> Running transaction check
---> Package kernel.x86_64 0:3.10.0-1160.114.2.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
==================================================================================================================================================================================================================
Package Arch Version Repository Size
==================================================================================================================================================================================================================
Installing:
kernel x86_64 3.10.0-1160.114.2.el7 updates 52 M
Transaction Summary
==================================================================================================================================================================================================================
Install 1 Package
Total size: 52 M
Installed size: 66 M
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : kernel-3.10.0-1160.114.2.el7.x86_64 1/1
Verifying : kernel-3.10.0-1160.114.2.el7.x86_64 1/1
Installed:
kernel.x86_64 0:3.10.0-1160.114.2.el7
Complete!
Получаем новую запись:
Hidden text
# grub2-mkconfig | grep -A 10 "menuentry 'CentOS"
menuentry 'CentOS Linux (3.10.0-1160.114.2.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.114.2.el7.x86_64-advanced-53a77eb0-927d-45ab-a110-1f00713931db' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 eabdf552-63da-4489-a0db-6a0cdde095b8
else
search --no-floppy --fs-uuid --set=root eabdf552-63da-4489-a0db-6a0cdde095b8
menuentry 'CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-53a77eb0-927d-45ab-a110-1f00713931db' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 eabdf552-63da-4489-a0db-6a0cdde095b8
else
search --no-floppy --fs-uuid --set=root eabdf552-63da-4489-a0db-6a0cdde095b8
menuentry 'CentOS Linux (0-rescue-f1e78ff605dd47a3bc0839d240d643c6) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-f1e78ff605dd47a3bc0839d240d643c6-advanced-53a77eb0-927d-45ab-a110-1f00713931db' {
load_video
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 eabdf552-63da-4489-a0db-6a0cdde095b8
else
search --no-floppy --fs-uuid --set=root eabdf552-63da-4489-a0db-6a0cdde095b8
fi
done
На самом деле при выполнении grub2-mkconfig он генерирует конфигурационный файл так:
1) Инспектирует содержимое /boot/.
2) Смотрит на скрипты в /etc/grub.d/:
# ls -la /etc/grub.d/
total 88
drwx------. 2 root root 182 Apr 10 2023 .
drwxr-xr-x. 158 root root 12288 Apr 14 23:16 ..
-rwxr-xr-x. 1 root root 8702 Dec 16 2022 00_header
-rwxr-xr-x. 1 root root 1043 Mar 22 2019 00_tuned
-rwxr-xr-x. 1 root root 232 Dec 16 2022 01_users
-rwxr-xr-x. 1 root root 10781 Dec 16 2022 10_linux
-rwxr-xr-x. 1 root root 10275 Dec 16 2022 20_linux_xen
-rwxr-xr-x. 1 root root 2559 Dec 16 2022 20_ppc_terminfo
-rwxr-xr-x. 1 root root 11169 Dec 16 2022 30_os-prober
-rwxr-xr-x. 1 root root 214 Dec 16 2022 40_custom
-rwxr-xr-x. 1 root root 216 Dec 16 2022 41_custom
-rw-r--r--. 1 root root 483 Dec 16 2022 README
3) Использует значения из /etc/default/grub.
Только после этого мы получаем конфигурационный файл.
Типовые задачи и их решение
Q: Как сделать, чтобы GRUB2 использовал по умолчанию определенный пункт меню?
A: Нужно воспользоваться утилитой grubby:
# grubby --info=ALL
index=0
kernel=/boot/vmlinuz-3.10.0-1160.114.2.el7.x86_64
args="ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8"
root=/dev/mapper/centos-root
initrd=/boot/initramfs-3.10.0-1160.114.2.el7.x86_64.img
title=CentOS Linux (3.10.0-1160.114.2.el7.x86_64) 7 (Core)
index=1
kernel=/boot/vmlinuz-3.10.0-1160.el7.x86_64
args="ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8"
root=/dev/mapper/centos-root
initrd=/boot/initramfs-3.10.0-1160.el7.x86_64.img
title=CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)
index=2
kernel=/boot/vmlinuz-0-rescue-f1e78ff605dd47a3bc0839d240d643c6
args="ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"
root=/dev/mapper/centos-root
initrd=/boot/initramfs-0-rescue-f1e78ff605dd47a3bc0839d240d643c6.img
title=CentOS Linux (0-rescue-f1e78ff605dd47a3bc0839d240d643c6) 7 (Core)
index=3
non linux entry
# grubby --set-default-index=1
# grubby --default-kernel
/boot/vmlinuz-3.10.0-1160.el7.x86_64
Q: Что делать, если загрузчик поврежден?
A: Мы можем проинсталлировать его заново командой grub2-install, загрузив операционную систему с установочного диска. Главное — помнить, что в качестве аргумента нужно использовать весь диск, а не просто раздел boot (в случае BIOS и MBR). Вы же помните, где находится первый этап загрузки?
Для UEFI можно переинсталлировать пакеты:
# yum reinstall grub2-efi shim
# reboot
Q: Как пересобрать конфигурацию GRUB2?
A: Просто командой grub2-mkconfig > /boot/grub2/grub.cfg.
Мы постарались собрать все аспекты работы загрузчика. По нашему опыту, при проблемах недостаточно знать только одну команду — решение требует комплексного знания предмета. Ну и нам было просто интересно. Ведь хороший сервисный инженер – это любопытный сервисный инженер.
Комментарии (18)
hogstaberg
10.06.2024 17:45+2убедиться, что есть UEFI;
пересобрать ядро с CONFIG_EFI_STUB, если этот параметр не включен;
проверить, чтобы ядро было выше версии 3.1;
ответить на вопрос: «Ради чего вы хотите потратить приличное количество времени на это?»
Последний пункт - сильное заявление, учитывая, что в современном мире прям нечасто встретишь кейс когда система не проходит по первым трём пунктам из коробки. В 99% случаев grub - пятое колесо у телеги и даром не сдался. Но все почему-то упорно продолжают жрать этот кактус.
А уж всё безумие утилит и мест, которые нужно крутить и править в современном rhel с uefi загрузкой - это вообще мрак и тлен.
radioxoma
10.06.2024 17:45Стаья давно плесенью покрылась. Ещё бы LILO вспомнили.
MBR в 2024 году? Я все машины (Arch + Win7) >5 лет назад на GPT перевёл без переустановки.hogstaberg
10.06.2024 17:45Вы таки не поверите что используют до сих пор во всяких энтерпрайзных rhel-like дистрибутивах. И нет, mbr там тоже не пахнет, но вот grub пихают с упорством, достойным лучшего применения.
JetHabr Автор
10.06.2024 17:45+2У ряда дистрибутивов "кактус" входит в заводскую комплектацию и тратить силы на его выкорчевывание совсем не хочется.
radioxoma
GRUB2 переусложнён и... не нужен? На десктопе достаточно refind (удобно иметь efi shell, gdisk, красивости, менять параметры ядра не загружая ОС) или голого efistub (обманчивая простота арча).
Штатный mkinitcpio может сразу упаковать всё (ядро, рамдиск, cmdline, splash image) в один efi executable и в esp положить. Перешёл на efistub, чтобы работал SecureBoot и недоверенные ОС вроде Windows не могли загружаться.
redfox0
systemd-boot ещё.
radioxoma
Когда смотрел, не понял чем он может быть удобен. Ну, кроме претензий на дефолтность из-за systemd в названии.
Refind был любовью с первого взгляда. До сих пор в esp валяется ради легкого доступа к shell и gdisk, хоть и везде уже UEFI грузит efistub напрямую.