GRUB 2 стоит почти везде по умолчанию, но он не единственный и не всегда лучший. Когда вам нужно поднять загрузку сотни машин по сети без единого диска, когда хочется минималистичный UEFI-загрузчик без меню на полэкрана, или когда надо собрать загрузочный образ для флешки и CD - в дело идут SYSLINUX, ISOLINUX, PXELINUX и systemd-boot. В этом уроке разберём, чем они отличаются от GRUB, как устроена сетевая загрузка по PXE, как systemd-boot читает UEFI и как руками править записи загрузки через efibootmgr.

Как это работает
Семейство Syslinux - это набор маленьких загрузчиков от одного проекта, каждый под свою среду. SYSLINUX грузится с раздела FAT (флешка, дискета), EXTLINUX - с ext2/3/4, btrfs и xfs, ISOLINUX живёт на оптических образах ISO 9660, а PXELINUX скачивается по сети при загрузке по PXE. Конфиг у всех общий по синтаксису: текстовый файл с метками LABEL, строками KERNEL и APPEND. Это намеренно простые загрузчики - они не понимают файловых систем так глубоко, как GRUB, зато весят килобайты и загружаются мгновенно.
PXE (Preboot Execution Environment) - это механизм в прошивке сетевой карты, который позволяет компьютеру стартовать вообще без локального диска. Машина шлёт DHCP-запрос, сервер отдаёт ей IP плюс два важных параметра: адрес TFTP-сервера и имя файла загрузчика. Прошивка качает этот файл по TFTP и передаёт ему управление. Для BIOS-машин файлом будет pxelinux.0, для UEFI - либо syslinux.efi, либо grubx64.efi. Дальше загрузчик по тому же TFTP тянет ядро и initrd, а корневую систему обычно монтирует по NFS или разворачивает из образа.
systemd-boot (старое имя - gummiboot) - это принципиально UEFI-only загрузчик. Он не умеет грузиться с BIOS и не разбирает файловые системы сам: вся его логика опирается на то, что UEFI-прошивка уже умеет читать раздел EFI (ESP, FAT32). systemd-boot просто показывает меню из найденных записей и запускает выбранный EFI-бинарь. Записи - это маленькие текстовые файлы в /boot/loader/entries/, а ядра лежат рядом на ESP. Отсюда его главное достоинство и ограничение: предельная простота при условии чистого UEFI.
Чтобы понять, где живёт UEFI-загрузка, надо знать про NVRAM. UEFI хранит список загрузочных записей прямо в энергонезависимой памяти материнской платы: каждая запись (Boot0000, Boot0001 и так далее) указывает на конкретный EFI-файл на ESP и имеет приоритет в порядке BootOrder. Именно этот список редактирует efibootmgr - он не трогает файлы загрузчика, а правит саму NVRAM.
Команды и примеры
Установка пакетов различается по семействам. Debian/Ubuntu:
Код: Выделить всё
apt install syslinux pxelinux syslinux-common isolinux
apt install systemd-boot # Ubuntu 24.04 и Debian 13
Код: Выделить всё
dnf install syslinux syslinux-tftpboot
dnf install systemd-boot-unsigned # Fedora 41+
Код: Выделить всё
DEFAULT linux
TIMEOUT 50
PROMPT 1
LABEL linux
KERNEL /boot/vmlinuz
APPEND initrd=/boot/initrd.img root=/dev/sda1 ro
Код: Выделить всё
/srv/tftp/
pxelinux.0
ldlinux.c32
pxelinux.cfg/default
vmlinuz
initrd.img
Код: Выделить всё
next-server 192.168.10.1;
filename "pxelinux.0";
Код: Выделить всё
bootctl install
bootctl status # показать версию и список записей
bootctl update # обновить загрузчик после апдейта systemd
Код: Выделить всё
title Fedora Linux 41
linux /vmlinuz-6.12.0
initrd /initramfs-6.12.0.img
options root=UUID=xxxx-xxxx ro quiet
Код: Выделить всё
efibootmgr -v
Код: Выделить всё
efibootmgr -c -d /dev/sda -p 1 -L "MyLinux" -l '\EFI\systemd\systemd-bootx64.efi'
Код: Выделить всё
efibootmgr -o 0003,0000,0002
efibootmgr -b 0005 -B
- Забытые модули .c32. Современный Syslinux вынес многое в отдельные файлы (ldlinux.c32, libcom32.c32, menu.c32). Если их нет рядом с pxelinux.0, загрузчик падает с ошибкой Failed to load или просто виснет.
- Пути в TFTP абсолютны от корня TFTP, а не от корня файловой системы. Лишний или недостающий слеш в filename ломает загрузку молча.
- systemd-boot не видит ядро на отдельном /boot, который не на ESP. Ядро и initrd должны лежать на том же FAT-разделе, что и загрузчик, либо ESP должен быть смонтирован в /boot.
- efibootmgr пишет в NVRAM, но требует загруженного модуля efivarfs и системы, реально стартовавшей в UEFI-режиме. В Legacy/BIOS-загрузке команда выдаст ошибку EFI variables are not supported.
- Обратные слеши в путях efibootmgr. UEFI использует backslash как разделитель, и забыть про это - классика. Берите путь в одинарные кавычки, чтобы shell не съел слеши.
- Secure Boot и неподписанные бинари. systemd-bootx64.efi и pxelinux под Secure Boot не запустятся без подписи или shim. На RHEL 10 для PXE обычно используют подписанный shim плюс GRUB, а не Syslinux.
- Блокировка TFTP/DHCP файрволом. nftables по умолчанию режет udp/69 и широковещательный DHCP - открывайте порты явно.
- Шаг 1. На UEFI-стенде выполните efibootmgr -v и запишите текущий BootOrder и номера записей - это точка отката.
- Шаг 2. Установите systemd-boot: bootctl install, затем проверьте bootctl status.
- Шаг 3. Создайте запись в /boot/loader/entries/test.conf на текущее ядро (возьмите versionы из uname -r и имена файлов в /boot).
- Шаг 4. Перезагрузитесь и убедитесь, что меню systemd-boot показывает вашу запись и система грузится.
- Шаг 5. Поднимите минимальный PXE: установите syslinux/pxelinux, разверните /srv/tftp с pxelinux.0 и .c32-модулями, запустите tftpd.
- Шаг 6. Настройте dnsmasq или isc-dhcp с next-server и filename, загрузите вторую виртуалку по сети (boot from network в настройках ВМ).
- Шаг 7. Через efibootmgr -o верните исходный BootOrder и при желании удалите тестовую запись через -B.
- Чем PXELINUX отличается от SYSLINUX и EXTLINUX по среде загрузки, и какой файл прошивка качает первым по TFTP в BIOS- и в UEFI-режиме?
- Какие два параметра DHCP обязательны для PXE-загрузки и за что отвечает каждый?
- Почему systemd-boot не работает на BIOS-машинах и что он перекладывает на прошивку UEFI?
- Где физически хранятся UEFI-загрузочные записи и какую часть системы правит efibootmgr?
- Что означают ключи -c, -d, -p и -l у efibootmgr и почему путь к EFI-файлу пишут с обратными слешами?
- Почему под Secure Boot SYSLINUX и systemd-bootx64.efi могут не запуститься и как эту проблему решают в RHEL?