Сломанный initramfs неприятен тем, что поломка скрыта от диагностических инструментов самой системы: машина не доходит ни до systemd, ни до журналов, ни до экрана входа. На мониторе либо паника ядра, либо приглашение аварийной оболочки dracut, либо чёрный экран с мигающим курсором. Причины почти всегда бытовые: прерванное обновление ядра, переполненный раздел boot, перенос диска на машину с другим контроллером хранения. Хорошая новость в том, что образ initramfs пересобирается из любого live окружения за полчаса аккуратной работы, и у процедуры есть один коварный нюанс с номером версии ядра, который ловит даже бывалых. Ниже полный маршрут: признаки поломки, диагностика, ручная сборка chroot, пересборка, проверка образа и профилактика на будущее.
Задача initramfs в раннем старте и признаки его поломки
Загрузчик GRUB читает с раздела boot два файла: ядро с именем вида vmlinuz-5.14.0-427.el9.x86_64 и сжатый архив initramfs-5.14.0-427.el9.x86_64.img размером в несколько десятков мегабайт. Внутри архива собрана ранняя пользовательская среда: модули дисковых контроллеров, поддержка файловых систем, утилиты для LVM и шифрования. Среда находит корневое устройство, монтирует его и передаёт управление systemd. Сборкой образа занимается dracut, причём в RHEL, Rocky Linux и AlmaLinux он по умолчанию собирает образ под конкретную машину: в него попадают только модули, нужные её оборудованию. Такой образ быстрее грузится и занимает меньше места, но болезненно переносит смену контроллера или переезд диска на другое железо. Отдельно стоит помнить, что initramfs пересобирается при каждой установке нового ядра, поэтому одна прерванная транзакция портит только один образ, и соседние ядра, если они сохранились, часто остаются рабочими.
Поломку распознают по характерным сообщениям. GRUB печатает error с путём к файлу образа и словами not found. Ядро падает с паникой Kernel panic и фразой Unable to mount root fs. Иногда загрузка подвисает на строчках dracut-initqueue timeout и заканчивается приглашением dracut:/#. Отдельный класс причин связан с ручной правкой: лишняя строка в /etc/dracut.conf.d, исключающая модуль lvm, превращает рабочую машину в неработоспособную после ближайшего обновления ядра, потому что образ собирается заново при каждой установке новой версии. Файл нулевого размера в boot после сбоя питания это тот же сценарий, только без правок: запись оборвалась, и утилита не успела дописать архив. Быстрый способ понять, какой образ обязан существовать в первую очередь, даёт команда grubby --default-kernel: она печатает ядро, которое грузится по умолчанию, и его файл initramfs критичен сильнее остальных.
Диагностика в аварийной оболочке dracut и файл rdsosreport
Аварийная оболочка dracut:/# устроена скромно, но польза в ней есть. Все логи раннего старта и вывод диагностических утилит dracut собирает в файл /run/initramfs/rdsosreport.txt, и первый вопрос к упавшей машине: читается ли этот файл и что в нём. Если добавить в командную строку ядра параметр rd.debug, вывод станет подробнее, а при активном systemd внутри initramfs сообщения дублируются в журнал, который просматривают командой journalctl -ab. Быстро сориентироваться помогает и список блочных устройств: cat /proc/partitions покажет, видит ли ядро диски вообще. Если устройств нет, проблема в модулях хранения, и лечить её придётся с live носителя, у которого набор модулей заведомо шире. Если устройства видны, но корень не монтируется, виноват либо сам initramfs, либо неверное имя корневого устройства в параметре root. Сохранённый rdsosreport.txt пригодится и позже: его прикладывают к заявке в системе учёта инцидентов, чтобы не пересказывать симптомы по памяти. В обоих случаях следующий шаг одинаковый: загрузка с live образа.
Подготовка live окружения, поиск разделов и активация LVM
Для работы подойдёт почти любой live дистрибутив с терминалом, но лучше держать под рукой образ того же семейства: установочный DVD RHEL, Rocky Linux или AlmaLinux умеет смонтировать найденную систему сам. В его меню есть готовый режим спасения: выбирают Troubleshooting, затем Rescue, и установщик монтирует систему в /mnt/sysimage, предлагая сразу войти в chroot. Ручной вариант универсальнее и работает с любого live образа, поэтому дальше разбирается он. В запущенной live сессии первым делом смотрят диски: lsblk -f выводит деревом разделов имена устройств, файловые системы и точки монтирования, а blkid добавляет UUID. В типовой раскладке RHEL 9 корень занимает логический том LVM, отдельный раздел boot размером около одного гигабайта держит ядра и образы initramfs, а на машинах с UEFI к ним добавляется раздел ESP, который монтируют в boot/efi. Логические тома в live среде не всегда активны сами, поэтому перед монтированием выполняют vgchange -ay. На шифрованных дисках том дополнительно открывают командой cryptsetup open, но это редкий сценарий со своими нюансами.
Ручная сборка окружения для chroot сводится к такой последовательности:
- загрузиться с live носителя и открыть терминал;
- определить корневое устройство по выводу lsblk -f и активировать тома LVM командой vgchange -ay;
- смонтировать корень в каталог /mnt;
- привязать виртуальные каталоги dev proc sys run внутрь /mnt;
- смонтировать раздел boot, а на машинах с UEFI ещё и boot efi;
- скопировать resolv.conf внутрь окружения, если планируется работа сети;
- войти в окружение командой chroot /mnt;
- после работы выйти из chroot и размонтировать всё в обратном порядке.
Команды для такой сборки выглядят так:
vgchange -ay
mount /dev/mapper/vg00-root /mnt
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
mount --bind /run /mnt/run
mount /dev/sda1 /mnt/boot
mount /dev/sda2 /mnt/boot/efi
cp /etc/resolv.conf /mnt/etc/resolv.conf
chroot /mnt
Имена устройств в примере условные, их подскажет lsblk на конкретной машине. Копия resolv.conf нужна, только если внутри chroot планируется работа dnf, например для переустановки ядра. Отдельно стоит убедиться, что раздел boot смонтирован из нужной системы, иначе пересборка запишет образ в пустой каталог live машины и создаст ложное чувство успеха. Быстрая проверка проста: вывод ls /mnt/boot должен показать файлы vmlinuz, а не пустоту.
В облачных средах вместо флешки используют образ восстановления провайдера либо отключают загрузочный диск и подключают его к вспомогательной виртуальной машине. Шаги с chroot от этого не меняются, меняется только способ добраться до диска. Виртуализация здесь скорее помогает: снапшот перед ремонтом снимает страх сделать хуже.
Пересборка initramfs утилитой dracut с явной версией ядра
Здесь прячется главный нюанс всей работы. Внутри chroot, собранного из live носителя, команда uname -r печатает версию ядра live системы, потому что само ядро не менялось. Если довериться ей и просто запустить dracut -f, утилита честно пересоберёт образ для ядра live машины и положит его в boot под именем с чужой версией, а пострадавший образ останется как был. Верную версию берут из списка установленных ядер:
ls /boot/vmlinuz-*
dracut --force --kver 5.14.0-427.el9.x86_64
Вариант с явным файлом выглядит так: dracut -f /boot/initramfs-5.14.0-427.el9.x86_64.img 5.14.0-427.el9.x86_64, а флаг --regenerate-all пересоберёт образы сразу для всех ядер, найденных на диске. Номер 5.14.0-427.el9.x86_64 здесь для примера, на конкретной машине он свой. Перед запуском полезно взглянуть на свободное место: df -h /boot. Переполненный раздел сам по себе ломает обновления, и если свободно меньше пары сотен мегабайт, старые ядра убирают утилитой dnf remove с полным именем пакета kernel-core и версией. По умолчанию dnf хранит три последних ядра и подчищает старые сам, но ручные эксперименты этот порядок нарушают. Если повреждён не только образ, но и пакет ядра, выручает dnf reinstall kernel-core: пакет вернёт и vmlinuz, и упакованный в него initramfs, после чего dracut всё равно собирает свежий образ под машину. Если же диск готовится к переезду на другое железо, образ собирают с флагом --no-hostonly: набор модулей в нём шире, и загрузка переживёт смену контроллера. Есть и тонкость про чужое окружение: когда образ собирается не из настоящей корневой файловой системы, dracut ожидает флаг --fstab и корректный /etc/fstab внутри chroot.
Проверка собранного образа командой lsinitrd и конфигурация GRUB
Собранный образ проверяют до перезагрузки. Команда lsinitrd с путём к файлу выводит содержимое архива, и в списке должны найтись модуль lvm, драйверы файловой системы и утилиты раннего старта; размер нового файла должен быть сопоставим с прежним. Список модулей исправного образа полезно сохранить в заметки заранее: после пересборки будет с чем сравнивать. Конфигурация GRUB чаще всего правок не требует: загрузчик ссылается на точное имя файла образа, и пересборка с тем же номером версии просто подменяет содержимое. Меню GRUB правят, только если ядро переустанавливалось с другим номером или конфигурация была сломана раньше: тогда выполняют grub2-mkconfig с выводом в файл конфигурации. На Legacy BIOS это /boot/grub2/grub.cfg, на UEFI в семействе RHEL конфигурация лежит внутри ESP, в /boot/efi/EFI/redhat/grub.cfg, и ESP обязан быть смонтирован. Отдельный штрих для систем с SELinux: файлы, записанные из live окружения, могут получить чужие контексты, поэтому внутри chroot выполняют restorecon -R /boot, а при сомнениях создают метку touch /.autorelabel, которая запустит переразметку при первом старте.
Выход из chroot, аккуратное размонтирование и первая загрузка
Заключительная часть требует терпения, а не скорости. Из chroot выходят командой exit, затем размонтируют всё в порядке, обратном монтированию, начиная с вложенных разделов:
exit
umount /mnt/boot/efi
umount /mnt/boot
umount /mnt/run
umount /mnt/sys
umount /mnt/proc
umount /mnt/dev
umount /mnt
reboot
Флешку вынимают при перезагрузке. Первую загрузку лучше встретить у консоли: если машина снова попадает в оболочку dracut, смотрят свежий rdsosreport.txt и проверяют, совпадает ли имя корневого устройства в параметре root с реальностью. После пересборки обычно остаётся одна из двух бед: неверное имя устройства или отсутствие нужного модуля хранения, и вторая лечится повторной сборкой с --no-hostonly. После успешного входа полезно сразу выполнить uname -r, убедиться, что загрузилось ожидаемое ядро, затем просмотреть журнал старта командой journalctl -b и проверить df -h /boot, чтобы понять, от чего система едва не отказалась стартовать.
Профилактика поломок загрузки свободным местом в boot и резервными копиями
Любую поломку initramfs дешевле предотвратить. Раздел boot держат свободным: одного гигабайта, рекомендованного в RHEL 9, хватает на три ядра с образами, но только если не копить архивы вручную. Обновления ядра не прерывают: отключение питания в момент работы dnf это классический сценарий усечённого initramfs, а в виртуальных машинах перед большим обновлением делают снапшот, который снимает почти весь риск. Перед экспериментами с модулями в /etc/dracut.conf.d текущий образ копируют в сторону, на другой раздел: вернуть заведомо рабочий файл быстрее, чем грузиться с live носителя. Прерванную транзакцию видно в dnf history, и её стоит закрыть до первой перезагрузки. Свободное место в boot удобно вынести в метрику мониторинга с порогом в 20 процентов: заполненный раздел предсказуемо ломает ближайшее обновление ядра, и лучше узнать об этом из алерта, чем из чёрного экрана. Наконец, в семействе Debian и Ubuntu та же проблема решается командой update-initramfs -u -k all внутри chroot, а сама логика live образа, chroot и явной версии ядра не меняется от дистрибутива к дистрибутиву. Описанный маршрут стоит один раз прогнать на тестовой машине, чтобы в ночь реальной поломки не искать образ, кабель и свободный USB порт.
Initramfs весит десятки мегабайт, но без них сервер превращается в тёплый шкаф. Паника на экране звучит страшнее, чем обстоит дело: раннее окружение пересобирается утилитой из самой системы, а ловушка с uname -r не сработает, если помнить простое правило: внутри chroot команда uname -r печатает чужую версию, номер ядра берут из /boot/vmlinuz-*. Дальше чистая механика: смонтировать, собрать, проверить, размонтировать. И в следующий раз, когда обновление ядра оборвётся на середине, вместо часа растерянности будут пятнадцать минут работы по знакомым шагам.