Від кнопки живлення до shell
Навіщо це
Section titled “Навіщо це”Між натисканням кнопки живлення і запрошенням входу минає кілька секунд, за які керування послідовно змінює чотирьох власників. Поки все працює, знати цей ланцюг вам не знадобиться.
Знадобиться, коли щось зламається. Система не завантажується після
оновлення ядра. Замість робочого столу з’явився emergency mode. Служба
руками запускається, а при завантаженні ні. Кожна така ситуація відповідає
конкретній ланці ланцюга, тож половина діагностики — це зрозуміти, до якої
ланки система взагалі дійшла.
Передумови. Режими виконання (модуль 2), PID 1 і дерево процесів (модуль 6).
Ланцюг
Section titled “Ланцюг”Починається все з прошивки. Процесор бере першу інструкцію з фіксованої адреси, де вона й лежить. Прошивка перевіряє та ініціалізує пам’ять, шини й контролери, після чого шукає, що завантажувати далі.
Сучасна прошивка — це UEFI. Вона розуміє файлову систему FAT32 і читає
завантажувач як звичайний файл з окремого розділу, який називається ESP
(EFI System Partition). Список записів лежить в енергонезалежній пам’яті
материнської плати, і його можна редагувати з працюючої системи
через efibootmgr.
Стара схема BIOS + MBR влаштована зовсім інакше: BIOS зчитує перші 512 байтів диска й виконує їх. У ці 512 байтів разом із таблицею розділів вміщається так мало коду, що завантажувач доводилося ділити на етапи. Звідти ж походять і обмеження MBR — чотири первинні розділи та 2 ТіБ, які GPT знімає обидва.
Завантажувач, GRUB чи systemd-boot, показує меню, знаходить образ ядра й initramfs і передає ядру параметри командного рядка. Цей рядок визначає, що ядро робитиме далі: де шукати корінь, чи вмикати налагоджувальний вивід, які драйвери вимкнути.
Ядро розпаковується, ініціалізує підсистеми, знаходить процесори й пам’ять, запускає драйвери і монтує initramfs.
Останнім ядро запускає перший процес режиму користувача, PID 1. Він особливий одразу з кількох боків: його не вбити звичайним сигналом, він усиновлює всіх процесів-сиріт (модуль 6), а якщо він завершиться, ядро зупинить систему.
systemd
Section titled “systemd”Класичний init запускав скрипти послідовно за номерами. Просто
й повільно: кожна служба чекала на попередню, навіть коли між ними
не було жодного зв’язку.
systemd натомість описує систему як граф залежностей і паралельно
запускає все, що можна запустити паралельно.
Одиниця, якою він керує, називається юнітом. Типів кілька: .service
для процесу, .socket для сокета, при зверненні до якого служба
запускається, .timer замість cron, .mount для точки монтування
і .target для групи юнітів.
Ціль варто розуміти не як рівень виконання, а як точку в графі.
multi-user.target означає, що система готова до роботи в консолі,
а graphical.target — що з графічним середовищем.
Найцікавіше тут — активація за сокетом. Systemd відкриває сокет одразу, а службу запускає лише при першому зверненні. Клієнт різниці не бачить, бо з’єднання приймається і чекає, зате завантаження не гальмує через служби, до яких узагалі ніхто не звертається.
Як це насправді в Linux
Section titled “Як це насправді в Linux”[ -d /sys/firmware/efi ] && echo 'UEFI' || echo 'BIOS (legacy)'Чи завантажена система через UEFI. Каталог існує лише в режимі UEFI.
efibootmgr -v 2>/dev/null | head; lsblk -o NAME,PARTTYPENAME,MOUNTPOINT | headЗаписи завантаження в пам’яті материнської плати і розділ ESP,
зазвичай змонтований у /boot/efi.
cat /proc/cmdlineПараметри, з якими завантажене поточне ядро — саме те, що передав завантажувач. Тут видно, звідки взято корінь і які опції застосовані.
lsinitramfs /boot/initrd.img 2>/dev/null | head -20 || lsinitrd 2>/dev/null | head -20Вміст initramfs: набір модулів, потрібних, щоб дістатися кореня.
Тут навмисно /boot/initrd.img — символьне посилання на образ типового
ядра. Якщо взяти /boot/initrd.img-$(uname -r), команда впаде саме тоді,
коли ситуація найцікавіша: після оновлення ядра, коли новий образ уже є,
а система досі виконує старе ядро, для якого образу може не бути.
Порівняти обидва — корисна вправа.
systemd-analyze; systemd-analyze blame | head -10Скільки тривало завантаження з розбивкою на прошивку, завантажувач, ядро й простір користувача — і які юніти забрали найбільше часу.
systemd-analyze critical-chainКритичний ланцюг: послідовність, що фактично визначила час завантаження. Оптимізувати має сенс лише те, що в ньому.
systemctl list-units --type=target --state=activesystemctl get-defaultАктивні цілі й ціль за замовчуванням.
journalctl -b -p err --no-pager | tail -10Помилки поточного завантаження. -b -1 покаже попереднє —
незамінне, коли система впала і встигла перезавантажитись.
Типові помилки розуміння
Section titled “Типові помилки розуміння”«BIOS і UEFI — те саме, просто нова назва». Це різні схеми. BIOS
виконує перші 512 байтів диска, а UEFI читає .efi-файл із розділу FAT32
і зберігає список записів у пам’яті материнської плати.
«initramfs потрібен для швидкості». Він потрібен, щоб розірвати коло: для монтування кореня потрібні драйвери, які лежать на самому корені.
«systemd — це просто init». Це менеджер служб із графом залежностей, активацією за сокетом, таймерами, точками монтування й журналом. Спірним його вважають саме через обсяг того, що він на себе забрав.
«Ціль — це рівень виконання». Цілі не впорядковані числом і не виключають одна одну, це просто точки синхронізації в графі.
«Служба працює руками, значить юніт правильний». Оточення в юніта
інше: немає ваших змінних, інший робочий каталог, stdout у journald.
Розбіжність найчастіше саме тут.
«Система не завантажилась, перевстановлю». Спершу подивіться
journalctl -b -1 -p err і параметри в /proc/cmdline. Найчастіше
винні дві речі: не перезібраний після оновлення ядра initramfs
і неправильний UUID кореня у /etc/fstab.
Перевір себе
Лабораторна
Section titled “Лабораторна”B1 — встановлення системи. Розмітка GPT, розділ ESP, завантаження
через UEFI і власний .service-юніт із залежностями. Обов’язкова частина —
навмисно зламати завантаження й полагодити його з аварійного режиму.
Джерела
Section titled “Джерела”- Nemeth та ін., UNIX and Linux System Administration Handbook, розділ 2
man 7 boot,man 1 systemd,man 5 systemd.unit,man 5 systemd.service- systemd for Administrators — серія від автора
- UEFI Specification — якщо потрібні деталі формату