Под капотом загрузчика
Привет, Хабр!
Мы, сервисные инженеры, сталкиваемся с 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.
Мы постарались собрать все аспекты работы загрузчика. По нашему опыту, при проблемах недостаточно знать только одну команду — решение требует комплексного знания предмета. Ну и нам было просто интересно. Ведь хороший сервисный инженер — это любопытный сервисный инженер.