Fallback initramfs что это manjaro
Ubuntu не загружается дальше initramfs
Пользователи, которые любят экспериментировать со своей операционной системой время от времени сталкиваются с ошибкой загрузки, когда система выводит приглашение ввода BusyBox с initramfs. Эта ошибка означает, что ядро не может загрузить корневой раздел, та файловая система, к которой у вас есть доступ из этого режима не имеет ничего общего с вашей системой. Это содержимое образа initramfs, которое содержит только самые необходимые компоненты, используемые ядром для загрузки системы.
В этом режиме будет сложно что-то исправить, но можно попытаться понять где находится причина проблемы. В этой статье мы рассмотрим что делать если Linux не загружается с initramfs. Такой проблеме подвержены все дистрибутивы, но мы рассмотрим решения на примере Ubuntu.
Почему Linux не загружается дальше initramfs
Если вы столкнулись с данной ошибкой, то после нескольких десятков секунд загрузки увидите такое сообщение:
1. Неверный корневой раздел в загрузчике
В данном случае она сообщает, что не может найти раздел /dev/sda10:
Alert: /dev/sda10 does not exist. Dropping to a shell
Очень часто такая ошибка возникает после манипуляций с разделами дисков, особенно изменения их размера. UUID диска меняется и ядро больше не может его найти. Вы можете посмотреть доступные в системе разделы с помощью команды:
В этом окружении есть BusyBox, а значит есть большинство утилит Unix. Вы можете примонтировать каждый из этих разделов с помощью команды mount и узнать где находится ваш новый корневой раздел, например:
mkdir /mnt
mount /dev/sda5 /mnt
ls
Вы также можете узнать здесь же UUID данного раздела диска, для этого выполните:
В данном случае, корневой раздел имеет имя /dev/sda5. Именно это имя можно передать ядру в конфигурации загрузчика Grub, а можно UUID, но если в этом нет крайней необходимости, то короткое имя использовать гораздо проще. Надо перезагрузить компьютер, в меню Grub выбрать нужную загрузочную запись и нажать клавишу E:
Далее найти пункт, начинающейся со слова linux и в нём параметр root. Его значение вместе со словом UUID надо стереть, а вместо него прописать имя корневого раздела:
После этого система загрузится, а вам останется только создать новый конфигурационный файл grub с помощью команды:
2. Повреждённая файловая система
Подобная ошибка может появляться также при серьезных ошибках в файловой системе, которые мешают примонтировать корневой раздел. Обычно, fsck восстанавливает файловую систему автоматически, но если проблема серьезная и грозит потерей данных, утилите надо подтверждение пользователя для работы. Тогда система показывает такую ошибку:
The root filesystem on /dev/sda5 requires a manual fsck
Вы можете прямо здесь же попытаться восстановить файловую систему. Для этого выполните:
Выводы
В этой статье мы разобрались что делать если в Linux не загружается initramfs, как посмотреть сообщение об ошибке, а также как устранить самые распространённые причины.
Модифицируем процесс загрузки с помощью утилиты make-initrd
Модифицируем процесс загрузки с помощью утилиты make-initrd
Упрощенный процесс загрузки ОС Linux
Загрузка ОС на устройстве с UEFI обычно проходит по следующему сценарию:
Размещение в оперативной памяти EFI загрузчика (например, grub) и передача управления ему;
EFI загрузчик записывает образ ядра в оперативную память и вызывает функцию start_kernel;
Ядро инициализирует себя, монтирует корень файловой системы и запускает процесс init, лежащий на корне (/init, /sbin/init или другой). Этим процессом может быть systemd, System V и другие;
Процесс init запускает сервисы и уже подготавливает систему для работы с пользователем.
Такая схема является вполне работоспособной. Но что, если мы хотим усложнить сценарий загрузки? Например, загрузиться с зашифрованного раздела или сетевого диска или, элементарно, проверить файловую систему перед загрузкой. На помощь приходит initramfs!
Что такое initramfs?
Initramfs (Initial ram file system) – образ файловой системы, загружаемый в оперативную память вместе с ядром. Основные задачи этого образа: монтирование реального корня файловой системы и запуск процесса init лежащего на нем.
Многие современные дистрибутивы Linux используют initramfs образы для загрузки системы. Вы можете убедиться в этом сами, найдя файл /boot/
Возможные сценарии использования initramfs
Внутри initramfs образа могут реализовываться разнообразные сценарии загрузки ОС. Все они ограничены лишь возможностями Linux, характеристиками устройства и вашей фантазией.
Достаточно популярными и широко используемыми сценариями являются:
Вывод приветственной картинки на экран;
Проверка целостности корневой файловой системы;
Загрузка с нестандартных файловых систем;
К экзотическим можно отнести:
Загрузку с образа корня, лежащего в интернете;
Загрузку с зашифрованного раздела;
Загрузку другой ОС с помощью системного вызова kexec.
Утилиты для создания initramfs образов
Разные дистрибутивы используют разные утилиты для создания initrd образов. Debian обычно используют для этого initramfs-tools, Red Hat – Dracut. Но в этой статье я хочу представить другую, менее известную утилиту – make-initrd.
Почему make-initrd?
make-initrd – утилита для создания initramfs образов, разрабатываемая нашим соотечественником Алексеем Гладковым. Сейчас она используется как основной сборщик initramfs в дистрибутиве ALT Linux.
Этот проект обладает рядом преимуществ:
Имеет модульную структуру. Разные логические части образа создаются разными модулями, именуемыми Features (фичами). Например, есть фича luks, отвечающая за внедрение сценария загрузки с зашифрованных разделов LUKS.
Создаваемые initramfs образы имеют простое внутреннее устройство.
Удобен для использования конечным пользователем. Многие части конфигурации определяются автоматически. Это достигается за счет отдельного модуля guess.
Утилита показала свою работоспособность на множестве различных дистрибутивов. Нам лично удавалось собрать и использовать эту утилиту на Ubuntu, Fedora, ALT Linux, Red OS, Astra Linux.
Генерируемые initramfs образы имеют относительно небольшой размер, а их сборка происходит достаточно быстро Для сравнения: initramfs-tools на моей машине генерирует образы размером 51Мб за 24 секунды. Образы же make-initrd весят всего 5Мб и создаются 10 секунд!
Проект продолжает активно развиваться. Со временем появляются новые фичи, улучшается архитектура утилиты и архитектура initramfs образов. Разработчик идет на контакт и всегда рад вашим патчам и предложениям:)
К сожалению, у make-initrd есть и недостатки:
Проект тестируется лишь на Fedora, Ubuntu и Alt Linux. И, хотя нам удавалось использовать его на других дистрибутивах, нет гарантии, что все будет работать гладко и везде.
Устройство initramfs образов, генерируемых make-initrd
В этом разделе описаны основные сведения по архитектуре образов, генерируемых make-initrd.
Сервисы
Создаваемые образы имеют сервисно-ориентированную архитектуру. При передаче управления программе /init порождается дерево сервисов, которые в дальнейшем взаимодействуют между собой. Последовательность их запуска и завершения определяется в процессе сборки образа и настраивается с помощью конфигурационных файлов LSB.
В системе есть несколько основных сервисов, на которых базируется основная логика работы:
udevd – обработчик событий ядра об изменении состояния устройств. При изменении состояния любого устройства он параллельно запускает фильтры (скрипты), добавляющие пользовательские события в очередь. Этот демон используется во многих дистрибутивах Linux.
ueventd – обработчик пользовательских событий. Этот демон запускает обработчики пользовательских событий. События внутри одной очереди обрабатываются последовательно, а сами очереди – параллельно.
polld – демон, ожидающий выполнения условий загрузки системы. Все, что он делает – один раз в заданное время проверяет условия запуска системы. Если они удовлетворены, запускается некоторый экшен. Скрипты проверки условий и экшена зависят от метода загрузки. Тем не менее, зачастую, их задача – проверить, что корень найден и переключить runlevel на второй уровень.
Runlevel
Runlevel определяет уровень запуска системы. Эти уровни отличаются от тех, что стандартно используются в Linux. В make-initrd номер уровня зависит от состояния загрузки системы. А от номера уровня, в свою очередь, зависит то, какие сервисы будут активны в текущий момент. В make-initrd предусмотрено всего 3 уровня:
Уровень 3 – означает, что реальный корень системы еще не примонтирован. На этом уровне происходит запуск и работа большинства сервисов.
Уровень 2 – означает, что реальный корень системы уже примонтирован. На этом происходит завершение большинства сервисов.
Уровень 9 – специальный уровень, на котором происходит подмена корня системы на реальный и запуск /sbin/init на нем.
Разберем пример загрузки с жесткого диска.
Последовательно запускаются различные сервисы, среди которых будут udevd, ueventd и polld;
После обнаружения устройства жесткого диска ядро сгенерирует соответствующее событие для демона udevd;
udevd просмотрит список своих правил. При нахождении правила на добавление блочного устройства запустится соответствующий обработчик (в make-initrd они называются фильтрами);
В какой-то момент ueventd запустит обработчик этого пользовательского события. Обработчик примонтирует жесткий диск;
Демон polld в очередной раз запустит скрипт проверки наличия корня. После его обнаружения запустится экшен, переключающий runlevel на второй уровень;
После переключения runlevel произойдет отключение большинства сервисов. Далее запустится сервис runinit, который установит runlevel на девятый уровень;
Процесс init произведет подмену корня и запустит /sbin/init ;
Устройство файловой системы initramfs образов
Initramfs образ, генерируемый make-initrd, имеет строгую структуру файловой системы. Поэтому при добавлении собственной фичи важно понимать, что и где должно лежать:
/init – программа, которой передается управление после инициализации ядра;
/etc/ – директория конфигураций;
/etc/rc.d/init.d/ – директория LSB конфигураций сервисов;
/etc/udev/rules.d/ – директория правил udevd;
/etc/initrd/method – файл содержащий текущий метод загрузки;
/etc/initrd/cmdline.d/ – директория описаний аргументов ядра;
/lib/uevent/filters/ – директория фильтров uevent событий;
/lib/uevent/handler/ – директория обработчиков uevent событий;
/lib/initrd/boot/method/ – директория скриптов методов загрузки;
/lib/initrd/boot/method/*/check – скрипт проверки условии активации метода загрузки;
/lib/initrd/boot/method/*/action – скрипт активации метода загрузки;
/lib/initrd/boot/scripts/ – директория подскриптов проверки условий метода загрузки;
/.initrd/ – директория, которую могут использовать сервисы и программы для внутренней работы;
/tmp/ – директория временных файлов.
Устройство генератора initramfs образов
process-config – Считывание конфигурационного файла. Во время ее выполнения происходит последовательный запуск целей guess и genimage;
guess – Угадывание конфигурационного файла;
create – Наполнение корня initramfs образа;
pack – Сортировка сервисов и упаковка initramfs образа в cpio архив. Зависит от create;
install – Установка образа в загрузочную директорию. Зависит от pack;
genimage – Вывод информационного сообщения о сборке образа. Зависит от install.
Процесс выполнения этих целей можно разбить на два больших этапа:
1. Угадывание дополнения к конфигурации (цель guess);
2. Сборка образа (цели create – genimage)
Этап угадывания конфигурации
Неправильное задание конфигурации грозит тем, что initramfs образ может оказаться излишне «тяжелым», а загрузка ОС будет происходить медленнее или не происходить вовсе. Например, если вы активировали фичу network, но не используете сеть в процессе загрузки, это грозит вам лишними секундами на настройку сетевых интерфейсов.
Именно для решения этих проблем в make-initrd был добавлен модуль guess. Он помогает оптимально сгенерировать или дополнить существующую конфигурацию, основываясь на окружении компьютера.
Guess использует разные модули для определения разных сфер образа. Например:
device – определяет модули ядра устройств;
keyboard – определяет модули ядра для работы с клавиатурой;
net – определяет модули ядра сетевых устройств;
root – определяет какие разделы нужно примонтировать, а также модули ядра для работы с ними;
smart-card – определяет конфигурацию фичи smart-card;
common – простой универсальный модуль, который может быть использован внутри фич.
Этот список не является исчерпывающим: описание остальных модулей можно посмотреть в README.md файлах модулей guess.
Этап сборки initramfs образа
Во время выполнения цели create создается временная директория, в которой заполняется корень initramfs образа. Корень заполняется в соответствии с переданной конфигурацией. Туда кладется все необходимое: приложения, библиотеки, файлы конфигурации и т.д. Но это еще не все: на последующих шагах корень еще будет дополняться.
Этап сборки образа может сколь угодно расширяться с помощью фич. Например, если активирована фича compress, то cpio архив будет дополнительно сжат с помощью одного из методов: gzip, lzma, bzip2 и т.п.
Фича – это независимый модуль сборщика initramfs образов. Фичи могут воздействовать практически на любой этап сборки образа. Например:
фича compress позволяет сжимать итоговый образ;
фича luks добавляет в initramfs утилиты и модули для работы с luks;
фича clean – очищает после себя рабочую директорию.
Структура проекта make-initrd
Выгрузим проект make-initrd из репозитория и посмотрим на его содержимое
Проект make-initrd очень хорошо структурирован. Давайте опишем, за что отвечают различные файлы и директории в проекте:
data/ – постоянная часть корня initramfs образа. Файлы, находящиеся в ней, будут присутствовать внутри почти всех образов;
datasrc/ – исходники утилит, устанавливаемые внутрь образа;
mk/config.mk – Makefile c постоянной частью конфигурации make-initrd (переменные путей и т.п.);
mk/functions.mk – Makefile с вспомогательными функциями make;
mk/make-initrd.mk – основной Makefile описывающий правила сборки initramfs образа;
tools/ – внутренние утилиты make-initrd;
utils/ – исходники внешних утилит make-initrd;
guess/ – директория guess модулей;
guess/*/config.mk – Makefile с описанием конфигурации guess модуля (переменные модуля, правила его активации). Он подключается вне зависимости от того, активен ли guess модуль или нет;
guess/*/rules.mk – Makefile с описанием правил отработки guess модуля. Он подключается, только если guess модуль активен;
features/ – директория фич;
features/*/data/ – часть корня initramfs образа, предоставляемая фичей;
features/*/datasrc/ – исходники утилит фичи, устанавливаемые внутрь initramfs;
features/*/guess/ – подскрипты модулей guess;
features/*/bin/ – вспомогательный утилиты сборки initramfs образа;
features/*/config.mk – Makefile с конфигурацией фичи (описание зависимых фич, переменных и т.п.). Он подключается вне зависимости от того, активна ли фича или нет;
features/*/rules.mk – Makefile с правилами сборки фичи. Он подключается только в случае, если фича активна.
Установка make-initrd
Сборка initramfs и запуск на реальной машине
ПРЕДУПРЕЖДЕНИЕ Перед генерацией initramfs образа обязательно сделайте backup.
Если система перестанет загружаться, откройте раздел с /boot на другой системе (например, через загрузочную флешку) и верните backup на место. Если вы не сделали backup, попробуйте загрузиться с помощью другого ядра. Это может сработать, так как по-умолчанию make-initrd собирает initramfs только для текущего ядра.
Перезапустим систему и попробуем загрузиться c ядра, для которого мы сгенерировали initramfs образ.
Добавление собственной фичи
Чтобы лучше разобраться с тем, как устроены фичи, давайте напишем свою – hello-usb.
Фича Hello USB
Примечание Исходный код фичи hello-usb можно взять здесь.
Напишем фичу hello-usb, добавляющую в initramfs функционал вывода сообщения “Hello USB!” при нахождении USB-устройства. Также добавим возможность указывать имя производителя устройства, для которого выводится сообщение.
Внутренняя логика работы нашей фичи, следующая:
Контроль добавления нового USB-устройства осуществляется с помощью udev правила /etc/udev/rules.d/99-hello-usb.rules : при добавлении любого USB-устройства вызывается фильтр /lib/uevent/filter/hello-usb
Внутри фильтра создается uevent событие hello-usb
Дерево файлов фичи следующее:
config.mk содержит описание фичи:
Через функцию feature-requires можно указывать зависимые фичи. Мы хотели получить модули ядра и udev-правила для работы с USB-устройствами, поэтому добавили в зависимости фичу usb.
rules.mk содержит правила сборки фичи:
feature/hello-usb/etc/initrd/cmdline.d/hello-usb – регистрирует опцию ядра usb-vendor:
feature/hello-usb/etc/udev/rules.d/99-hello-usb.rules – udev правило, запускающее фильтр. Число в начале имени нужно для задания порядка его обработки. В нашем случае было важно, чтобы правило hello-usb отработало позже, чем 60-fido-id (т.к. оно выставляет тег security-device ). Поэтому мы выставили любое число больше 60 – это 99.
Подробнее о udev правилах можно прочитать здесь.
Обратите внимание на простоту этого скрипта. Это связано с тем, что udev может запустить несколько таких скриптов одновременно, а это может привести к состоянию гонки. Именно поэтому логика большинства фильтров крайне проста – передать событие uevent, который обработает его последовательно.
feature/hello-usb/lib/uevent/handlers/060-hello-usb – обработчик события hello-usb. Uevent передает управление обработчикам в соотвествии с их номером. В нашем случае порядок обработки нашего события не важен, и мы выставили случайный номер – 60.
Соберем make-initrd с добавленной фичей:
Настройка и генерация initrd образа
Обычно файл с конфигурацией выглядит следующим образом:
Здесь написано, что вся конфигурация будет определена автоматически. Увидеть «угаданную» конфигурацию можно с помощью команды:
Вы можете попросить make-initrd запускать только определенные guess модули. Например, можно попросить «угадывать» только модули ядра и фичи необходимые для монтирования корня и работы с клавиатурой:
Попробуем теперь собрать intird образ вместе с фичей hello-usb. Подправим конфигурацию
И запустим сборку образа:
Перейдем к проверке нашего образа на виртуальной машине.
Запуск в qemu
Проверку образа будем производить с помощью qemu. Установим необходимые пакеты:
В процессе работы мы планируем пробрасывать USB-устройство на виртуальную машину. Чтобы это сделать, необходимо узнать его адрес на USB-шине:
Мы хотим пробросить устройство, имеющее класс Mass Storage (флешку). В нашем случае оно находится на первой шине и втором порту.
Перейдем к запуску:
После запуска системы сначала отобразится вывод ядра, а затем вывод самого initrd. Если вы все сделали правильно, в какой-то момент увидите вывод обработчика событий hello-usb:
На этом, увы, ваша система зависнет:) Это связано с тем, что initramfs будет продолжать искать устройство с корнем, но оно не проброшено в qemu. К счастью, есть возможность экстренно перейти в rescue консоль: для этого надо нажать клавиши ** + **.
В ней можно изучить окружение initramfs образа:
* Убедитесь, что файловая структура, описанная ранее, соответствует действительности;
* Изучите список активных процессов;
* Посмотрите логи в /var/log/ ;
* Посмотрите содержимое других файлов.
Вы всегда можете запустить rescue консоль, если имеются какие-либо проблемы при запуске. В ней возможно:
Изучить логи сервисов;
Примонтировать корень вручную и запуститься с него;
Запустить отладчик (если добавлена фича debug-tools).
Передача аргументов ядра
Запустим qemu с аргументом ядра usb-vendor
Заметьте, если указать другое имя производителя, то в лог может ничего не вывестись.
Популярные опции ядра, которые поддерживает initramfs можно посмотреть здесь
Проверка на реальной машине
После того, как вы убедились, что initramfs образ работает в qemu, можно проверить его на реальной машине. Но здесь могут возникнуть некоторые нюансы.
Мы покажем, как это сделать, на примере GRUB.
Настройка аргументов ядра в GRUB
Откроем файл /etc/default/grub. Его содержимое выглядит примерно следующим образом:
Подробнее об опциях grub можно прочитать здесь
Для генерации конфигурации второго уровня выполним команду:
Разбор полученной конфигурации является уже более сложной задачей и выходит за рамки этой статьи. Тем не менее посмотреть на файл /boot/grub/grub.cfg все равно будет полезно:) Подробную информацию о его конфигурации grub можно найти здесь.
Добавим в аргументы ядра, параметр usb-vendor. Для этого зададим в файле /etc/default/grub переменную GRUB_CMDLINE_LINUX_DEFAULT :
И снова обновим конфигурацию:
Перезапустите систему и посмотрите на результат.
Вывод
Естественно, фича hello-usb не раскрывает всю мощь использования make-initrd. Если вы хотите рассмотреть более живые примеры фич, посмотрите исходники фич:
sshfsroot. – фича для загрузки с сетевых дисков по протоколу ssh;
luks – фича для загрузки с зашифрованных разделов;
raid – фича для загрузки с raid разделов.
В первые две, кстати, мы недавно добавили возможность для аутентификации по смарт-карте.
Обратите внимание насколько архитектура этих фичей совпадает с той, что мы реализовывали в hello-usb. Такая структурированность упрощает процесс разработки, и вы можете опираться на нее.
Make-initrd также удобен и для конечного использования. Такая крупная ОС, как ALT Linux, использует его в своих дистрибутивах в качестве основного генератора initramfs образов, в частности на таких продуктах, как “Альт Рабочая станция” и “Альт Сервер”. Это ли не показывает его широкую направленность?
На десктопных платформах вы можете добиться желаемого с помощью пары строк в конфигурационном файле, а порой полностью автоматически. Хотите добавить загрузку c сетевого раздела, используя sshfs? Просто напишите FEATURE += sshfsroot в файле конфигурации, а в опциях ядра укажите адрес сервера. Хотите добавить загрузку с RAID или LVM разделов? Ничего делать не надо! Если ваш корень лежит на таком разделе, make-initrd автоматически подберет правильную конфигурацию.
На серверных решениях вы можете добиться быстрой загрузки за счет высокой конфигурируемости образов. Вы всегда можете отключить любые ненужные вам фичи, тормозящие загрузку вашей системы. За счет обилия имеющегося функционала можно реализовать загрузку практически любой сложности. А если какого-то функционала будет не хавать, можно быстро реализовать его самостоятельно.