Загрузка Linux обычно выглядит скучно: нажал кнопку, побежали строчки, появился логин. Но внутри за пару секунд происходит цепочка шагов, где любой мелкий косяк превращается в “чёрный экран”, “зависло на A start job is running…” или “почему сервер грузится 3 минуты”.
В этой части рубрики “Linux под капотом” разберу загрузку от момента включения питания до того, как ты видишь приглашение входа. Без мифов и без “оно само”. С командами, где это можно руками потрогать и измерить.
Карта загрузки в двух словах
Если свести весь процесс к “кто за кем”:
- прошивка (BIOS/UEFI) выбирает, откуда грузиться;
- загрузчик (чаще GRUB, иногда systemd-boot) загружает ядро и initramfs;
- ядро Linux поднимает драйверы, память, планировщик и стартует раннее пользовательское окружение из initramfs;
- initramfs находит корневую ФС и передаёт управление системе (init);
- init (обычно systemd) запускает сервисы, монтирует всё нужное, поднимает сеть, логин и т.д.
Дальше по шагам, что именно происходит и где это смотреть.
Шаг 1: BIOS/UEFI выбирает, откуда грузиться
На железе первым просыпается прошивка. В старом мире это BIOS, в новом — UEFI. Для Linux админа важны две вещи: режим загрузки (UEFI или Legacy) и то, где лежит загрузчик.
Как понять, в каком режиме загрузилась система:
[ -d /sys/firmware/efi ] && echo "UEFI" || echo "Legacy BIOS"
Если UEFI, значит где-то есть EFI-раздел (обычно FAT32), и в нём лежат .efi-файлы загрузчика. Если Legacy, история больше похожа на “MBR + GRUB stage”.
Посмотреть EFI-раздел и как он смонтирован:
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,PARTUUID findmnt /boot/efi || true
Если на сервере внезапно поменялся режим (например, перенос диска, виртуалка, пересоздание VM), дальше начинается цирк: GRUB стоит “не туда”, запись в NVRAM не совпадает, systemd-boot не видит ядро. Поэтому шаг “UEFI/Legacy” — это не формальность, а диагностика в первые 30 секунд.
Шаг 2: загрузчик (GRUB или systemd-boot) и его работа
Загрузчик делает простую, но критичную вещь: выбирает ядро, передаёт параметры командной строки, подцепляет initramfs и запускает ядро. В большинстве дистрибутивов это GRUB. В некоторых системах (особенно чистых UEFI-сборках) может быть systemd-boot.
Если GRUB, то чаще всего конфиг живёт здесь:
ls -l /boot/grub/ /boot/grub2/ 2>/dev/null || true ls -l /etc/default/grub 2>/dev/null || true
Если systemd-boot:
bootctl status 2>/dev/null || true ls -l /boot/loader/entries 2>/dev/null || true
Самое полезное в повседневной жизни — параметры ядра. Они решают “какой root”, “как логировать”, “в какой таргет грузиться”, “вырубить ли splash и увидеть ошибки”.
Посмотреть, с чем ядро реально загрузилось:
cat /proc/cmdline
Два параметра, которые часто выручают при отладке загрузки:
systemd.unit=rescue.target— загрузка в rescue (минимум сервисов);systemd.unit=emergency.target— ещё жёстче, по сути “влететь в shell и не трогать лишнее”.
Если система падает на монтировании, сети, кривом сервисе — такие режимы позволяют зайти и чинить, а не смотреть на вечный прогресс-бар.
Шаг 3: ядро Linux стартует и пишет первые логи
Ядро загружается в память, распаковывается, инициализирует железо, драйверы, планировщик, память, файловые системы. Всё это видно в kernel ring buffer — то самое, что показывает dmesg.
Посмотреть сообщения ядра текущей загрузки:
dmesg -T | less
А если нужно поймать именно ошибки и предупреждения:
dmesg -T --level=err,warn | less
На этом этапе типовые проблемы выглядят так: “не нашёл диск”, “не поднялся драйвер”, “ждал устройство”, “не смог смонтировать root”. Если root не смонтировался — загрузка дальше не пойдёт. И тут в игру вступает initramfs.
Шаг 4: initramfs — “временная система”, которая ищет твой root
initramfs (или initrd) — это минимальная файловая система в памяти. Внутри скрипты и драйверы, которые нужны, чтобы:
- подцепить RAID/LVM/шифрование (LUKS);
- найти нужный диск;
- смонтировать корень и передать управление основному init.
В Debian/Ubuntu initramfs обычно собирается через update-initramfs. Быстро посмотреть, какие образы есть:
ls -lh /boot/initrd* /boot/initramfs* 2>/dev/null || true uname -r
Пересобрать initramfs для текущего ядра (когда, например, добавил драйвер, поменял LVM, правил hooks):
sudo update-initramfs -u -k "$(uname -r)"
Самый частый сценарий “всё работало, а потом не грузится” — поменяли диски/UUID, правили /etc/fstab, пересобрали RAID, или переехали в другую виртуалку, а initramfs остался со старой картиной мира. В итоге ядро стартует, а root найти не может.
Шаг 5: systemd как PID 1 и почему именно он решает, “быстро” или “долго”
Когда root смонтирован, ядро запускает первый пользовательский процесс — init. На большинстве современных систем это systemd. Он становится PID 1 и дальше дирижирует всем: монтирование, сервисы, сеть, логирование, таймеры, зависимости.
Проверить, кто у тебя PID 1:
ps -p 1 -o pid,comm,args
Посмотреть, во что система загрузилась (target):
systemctl get-default systemctl list-units --type=target --state=active
Вот тут и рождаются “долгие загрузки”. Не потому что “Linux медленный”, а потому что какой-то unit ждёт сеть, диск, DNS, таймаут монтирования или внешний ресурс. systemd честно ждёт, пока истечёт таймаут, и ты получаешь лишние 90 секунд на ровном месте.
Как посмотреть, что тормозит загрузку
systemd даёт три команды, которые я считаю обязательными в арсенале.
Общее время загрузки по этапам (прошивка, загрузчик, ядро, userspace):
systemd-analyze
Самые долгие юниты (не всегда “виновники”, но это отличная зацепка):
systemd-analyze blame | head -n 30
Цепочка зависимостей до конкретного проблемного юнита. Очень помогает, когда “виновник” не тот, кто висит, а тот, кого он ждёт:
systemd-analyze critical-chain
Если видишь что-то вроде dev-disk-by... или network-online.target с большим временем — это классика. Диск не появился вовремя, DNS не поднялся, сетевой “online” ждёт бесконечно, а сервер просто стоит и ждёт, как дисциплинированный.
Где смотреть логи загрузки: journalctl и dmesg
Для диагностики я почти всегда начинаю с лога текущего бут-цикла.
Логи текущей загрузки:
journalctl -b -0
Логи предыдущей загрузки (когда “упало и перезагрузилось”, а ты пришёл уже после):
journalctl -b -1
Только ошибки текущей загрузки:
journalctl -b -0 -p err
Если журнал не сохраняется между перезагрузками, диагностика превращается в гадание. Включается это просто: нужен каталог /var/log/journal и рестарт journald.
sudo mkdir -p /var/log/journal sudo systemctl restart systemd-journald
После этого journalctl -b -1 станет реально полезным, а не “пусто, потому что так решили по умолчанию”.
Мини-лабораторка: измерь загрузку и найди узкое место
Этот блок можно прогнать на любой Ubuntu/Debian (и вообще на большинстве systemd-систем). Ничего опасного, только наблюдение.
1) Зафиксируй времена загрузки и топ медленных юнитов:
systemd-analyze systemd-analyze blame | head -n 25 systemd-analyze critical-chain
2) Найди один долгий юнит и посмотри подробности (что он делает и почему ждёт):
systemctl status ИМЯ_ЮНИТА journalctl -b -0 -u ИМЯ_ЮНИТА --no-pager
3) Проверь, не упёрся ли сервер в ожидание диска/монтажа. Если в выводах часто мелькают монтирования:
systemctl --failed findmnt -a | head cat /etc/fstab
Если в /etc/fstab есть сетевые шары или “второстепенные” диски, которые не всегда доступны, их можно делать более мягкими (например, через nofail и разумные timeout-опции). Но это уже тема для отдельной заметки: “как не убивать загрузку из-за одного капризного диска”.
Что дальше в рубрике
Следующий логичный шаг — разбор systemd глубже: unit-файлы, зависимости, targets, таймеры, почему network-online.target иногда зло, и как делать сервисы так, чтобы они стартовали предсказуемо.
А ещё отдельно стоит разобрать initramfs на реальных кейсах: LUKS, LVM, RAID, перенос дисков, восстановление после кривого fstab. Там много боли, но зато после этого “не грузится сервер” перестаёт звучать как приговор.