Ошибка сначала вам нужно загрузить ядро linux

Обновлено: 04.07.2024

Если вы читали предыдущие статьи, то знаете о моём новом увлечении низкоуровневым программированием. Я написал несколько статей о программировании на ассемблере для x86_64 Linux и в то же время начал погружаться в исходный код ядра Linux.

Мне очень интересно разобраться, как работают низкоуровневые штуки: как программы запускаются на моём компьютере, как они расположены в памяти, как ядро управляет процессами и памятью, как работает сетевой стек на низком уровне и многое другое. Итак, я решил написать еще одну серию статей о ядре Linux для архитектуры x86_64.

Обратите внимание, что это не официальная документация, а просто обучение и обмен знаниями.

Необходимые знания

  • Понимание кода на C
  • Понимание кода ассемблера (синтаксис AT&T)

Я начал писать эту книгу во времена ядра Linux 3.18, и многое могло измениться с тех пор. Если есть изменения, я буду соответственно обновлять статьи.

Хотя это статьи о ядре Linux, мы пока не дошли до него — по крайней мере, в этом параграфе. Как только вы нажмете волшебную кнопку питания на своём ноутбуке или настольном компьютере, он начинает работать. Материнская плата посылает сигнал к блоку питания. После получения сигнала он обеспечивает компьютеру необходимое количество электроэнергии. Как только материнская плата получает сигнал «Питание в норме», то пытается запустить CPU. Тот сбрасывает все оставшиеся данные в своих регистрах и устанавливает предопределённые значения для каждого из них.

У процессоров 80386 и более поздних версий после перезагрузки должны быть такие значения в регистрах CPU:


Процессор начинает работать в реальном режиме. Давайте немного вернемся назад и попытаемся понять сегментацию памяти в этом режиме. Реальный режим поддерживается на всех x86-совместимых процессорах: от 8086 до современных 64-разрядных процессоров Intel. В процессоре 8086 используется 20-битная шина адресов, то есть он может работать с адресным пространством 0-0xFFFFF или 1 мегабайт . Но у него есть только 16-битные регистры с максимальным адресом 2^16-1 или 0xffff (64 килобайта).

Сегментация памяти нужна для использования всего доступного адресного пространства. Вся память делится на небольшие сегменты фиксированного размера по 65536 байт (64 КБ). Поскольку с 16-битными регистрами мы не можем обратиться к памяти выше 64 КБ, был разработан альтернативный метод.

Адрес состоит из двух частей: 1) селектор сегмента с базовым адресом; 2) смещение от базового адреса. В реальном режиме базовым адресом селектора сегмента является селектор сегмента * 16 . Таким образом, чтобы получить физический адрес в памяти, нужно умножить часть селектора сегмента на 16 и добавить к нему смещение:


Например, если у регистра CS:IP значение 0x2000:0x0010 , то соответствующий физический адрес будет таким:


Но если взять селектор наибольшего сегмента и смещение 0xffff:0xffff , то получается адрес:


то есть 65520 байт после первого мегабайта. Поскольку в реальном режиме доступен только один мегабайт, 0x10ffef становится 0x00ffef с отключенной линией A20.

Хорошо, теперь мы немного знаем о реальном режиме и адресации памяти в этом режиме. Вернемся к обсуждению значений регистров после сброса.

Регистр CS состоит из двух частей: видимого селектора сегментов и скрытого базового адреса. Хотя базовый адрес обычно формируется путём умножения значения селектора сегмента на 16, но во время аппаратного сброса селектор сегмента в регистре CS получает значение 0xf000 , а базовый адрес — 0xffff0000 . Процессор использует этот специальный базовый адрес, пока не изменится CS.

Начальный адрес формируется добавлением базового адреса к значению в регистре EIP:


Мы получаем 0xfffffff0 , что на 16 байт ниже 4 ГБ. Эта точка называется вектором сброса. Это расположение в памяти, где CPU ждёт первую инструкцию для выполнения после сброса: операцию перехода (jmp), которая обычно указывает на точку входа BIOS. Например, если посмотреть исходный код coreboot ( src/cpu/x86/16bit/reset16.inc ), мы увидим:


Здесь мы видим код операции (опкод) jmp , а именно 0xe9 , и адрес назначения _start16bit - ( . + 2) .

Мы также видим, что раздел reset составляет 16 байт, и он компилируется для запуска с адреса 0xfffff0 ( src/cpu/x86/16bit/reset16.ld ):


Теперь запускается BIOS; после инициализации и проверки оборудования BIOS необходимо найти загрузочное устройство. Порядок загрузки сохраняется в конфигурации BIOS. При попытке загрузки с жёсткого диска BIOS пытается найти загрузочный сектор. На дисках с разметкой разделов MBR загрузочный сектор хранится в первых 446 байтах первого сектора, где каждый сектор равен 512 байтам. Последние два байта первого сектора — 0x55 и 0xaa . Они показывают BIOS, что это загрузочное устройство.


Собираем и запускаем:

nasm -f bin boot.nasm && qemu-system-x86_64 boot

QEMU получает команду использовать двоичный файл boot , который мы только что создали как образ диска. Так как двоичный файл, сгенерированный выше, удовлетворяет требованиям загрузочного сектора (начало в 0x7c00 и завершение магической последовательностью), то QEMU будет рассматривать двоичный файл как главную загрузочную запись (MBR) образа диска.


В этом примере мы видим, что код выполняется в 16-битном реальном режиме и начинается с адреса 0x7c00 в памяти. После запуска он вызывает прерывание 0x10, которое просто печатает символ ! ; заполняет оставшиеся 510 байт нулями и заканчивается двумя волшебными байтами 0xaa и 0x55 .

Двоичный дамп можно посмотреть утилитой objdump :

nasm -f bin boot.nasm
objdump -D -b binary -mi386 -Maddr16,data16,intel boot

Конечно, в реальном загрузочном секторе — код для продолжения процесса загрузки и таблица разделов вместо кучи нулей и восклицательного знака :). С этого момента BIOS передаёт управление загрузчику.

Примечание: как объясняется выше, CPU находится в реальном режиме; где вычисление физического адреса в памяти происходит следующим образом:


У нас только 16-битные регистры общего назначения, а максимальное значение 16-битного регистра 0xffff , поэтому на самых больших значениях результат будет:


где 0x10ffef равно 1 МБ + 64 КБ - 16 байт . В процессоре 8086 (первый процессор с реальным режимом) 20-битная адресная линия. Поскольку 2^20 = 1048576 , то фактически доступная память составляет 1 МБ.

В целом адресация памяти реального режима выглядит следующим образом:


В начале статьи написано, что первая инструкция для процессора находится по адресу 0xFFFFFFF0 , что намного больше 0xFFFFF (1 МБ). Как CPU получить доступ к этому адресу в реальном режиме? Ответ в документации coreboot:

0xFFFE_0000 - 0xFFFF_FFFF: 128 килобайт ROM транслируются в адресное пространство

В начале выполнения BIOS находится не в RAM, а в ROM.

Ядро Linux можно загружать разными загрузчиками, такими как GRUB 2 и syslinux. В ядре есть протокол загрузки, который определяет требования к загрузчику для реализации поддержки Linux. В данном примере мы работаем с GRUB 2.

Продолжая процесс загрузки, BIOS выбрал загрузочное устройство и передал управление загрузочному сектору, выполнение начинается с boot.img. Из-за ограниченного объёма это очень простой код. Он содержит указатель для перехода к основному образу GRUB 2. Тот начинается с diskboot.img и обычно хранится сразу после первого сектора в неиспользуемом пространстве перед первым разделом. Приведённый выше код загружает в память остальную часть образа, который содержит ядро GRUB 2 и драйверы для обработки файловых систем. После этого выполняется функция grub_main.

Функция grub_main инициализирует консоль, возвращает базовый адрес для модулей, устанавливает корневое устройство, загружает/парсит конфигурационный файл grub, загружает модули и т.д. В конце выполнения она переводит grub в нормальный режим. Функция grub_normal_execute (из исходного файла grub-core/normal/main.c ) завершает последние приготовления и показывает меню для выбора операционной системы. Когда мы выбираем один из пунктов меню grub, запускается функция grub_menu_execute_entry , которая выполняет команду grub boot и загружает выбранную ОС.

Как указано в протоколе загрузки ядра, загрузчик должен прочитать и заполнить некоторые поля заголовка установки ядра, который начинается со смещения 0x01f1 от кода установки ядра. Это смещение указано в скрипте линкера. Заголовок ядра arch/x86/boot/header.S начинается с:


Загрузчик должен заполнить этот и остальные заголовки (которые помечены только как тип write в протоколе загрузки Linux, как в данном примере) значениями, которые получил из командной строки или рассчитал во время загрузки. Сейчас мы не будем подробно останавливаться на описаниях и пояснениях для всех полей заголовка. Позже обсудим, как ядро их использует. Описание всех полей см. в протоколе загрузки.

Как видим в протоколе загрузки ядра, память будет отображаться следующим образом:


Итак, когда загрузчик передаёт управление ядру, оно начинается с адреса:


где X — адрес загрузочного сектора ядра. В нашем случае X равен 0x10000 , как видно в дампе памяти:


Загрузчик перенёс ядро Linux в память, заполнил поля заголовка, а затем перешёл на соответствующий адрес памяти. Теперь мы можем перейти непосредственно к коду установки ядра.

Наконец-то мы в ядре! Хотя технически оно ещё не запущено. Сначала часть установки ядра должна кое-что настроить, в том числе декомпрессор и некоторые вещи с управлением памятью. После всего этого она распакует настоящее ядро и перейдёт к нему. Выполнение установки начинается в arch/x86/boot/header.S с символа _start.

На первый взгляд это может показаться немного странным, так как перед ним есть несколько инструкций. Но давным-давно у ядра Linux был собственный загрузчик. Теперь же если запустить, например,



Он нужен для загрузки операционной системы с поддержкой UEFI. Его устройство рассмотрим в следующих главах.

Фактическая точка входа для установки ядра:


Точка входа установки ядра:


Здесь мы видим код операции jmp ( 0xeb ), который переходит к точке start_of_setup-1f . В нотации Nf , например, 2f ссылается на локальную метку 2: . В нашем случае это метка 1 , которая присутствует сразу после перехода, и она содержит остальную часть заголовка setup. Сразу после заголовка установки мы видим раздел .entrytext , который начинается с метки start_of_setup .

Это первый фактически выполняемый код (кроме предыдущих инструкций перехода, конечно). После того, как часть установки ядра получает управление от загрузчика, первая инструкция jmp находится по смещению 0x200 от начала реального режима ядра, то есть после первых 512 байт. Это можно увидеть как в протоколе загрузки ядра Linux, так и в исходном коде grub2:


В нашем случае ядро загружается по адресу 0x10000 . Это означает, что после запуска установки ядра регистры сегментов будут иметь следующие значения:

gs = fs = es = ds = ss = 0x10000
cs = 0x10200

После перехода к start_of_setup ядро должно сделать следующее:

  • Убедиться, что все значения регистров сегментов одинаковы
  • При необходимости настроить правильный стек
  • Настроить bss
  • Перейти к коду C в arch/x86/boot/main.с

Прежде всего ядро проверяет, что регистры сегментов ds и es указывают на один и тот же адрес. Затем очищает флаг направления с помощью инструкции cld :


Как я писал ранее, grub2 по умолчанию загружает код установки ядра по адресу 0x10000 , а cs по адресу 0x10200 , потому что выполнение начинается не с начала файла, а с перехода сюда:


Это смещение на 512 байт от 4d 5a. Также необходимо выровнять cs с 0x10200 до 0x10000 , как и все остальные регистры сегментов. После этого устанавливаем стек:


Эта инструкция помещает на стек значение ds , за ним следуют адрес метки 6 и инструкция lretw , которая загружает адрес метки 6 в регистр счётчика команд и загружает cs со значением ds . После этого у ds и cs будут одинаковые значения.

Почти весь этот код — часть процесса подготовки окружения для языка C в реальном режиме. Следующий шаг — проверить значение регистра ss и создать корректный стек, если значение ss неверное:


Это может инициировать три разных сценария:

  • у ss допустимое значение 0x1000 (как у всех остальных регистров, кроме cs )
  • у ss недопустимое значение, и флаг CAN_USE_HEAP установлен (см. ниже)
  • у ss недопустимое значение, и флаг CAN_USE_HEAP не установлен (см. ниже)
  • У ss допустимое значение ( 0x1000 ). В этом случае мы переходим к метке 2:

Здесь мы устанавливаем выравнивание регистра dx (который содержит значение sp , указанное загрузчиком) по 4 байтам и проверяем на нуль. Если он равен нулю, то помещаем в dx значение 0xfffc (выровненный по 4 байтам адрес перед максимальным размером сегмента 64 КБ). Если он не равен нулю, то продолжаем использовать значение sp , заданное загрузчиком ( 0xf7f4 в нашем случае). Затем помещаем значение ax в ss , что сохраняет правильный адрес сегмента 0x1000 и устанавливает правильный sp . Теперь у нас есть правильный стек:


  • Во втором сценарии ss != ds . Сначала помещаем значение _end (адрес конца кода установки) в dx и проверяем поле заголовка loadflags , используя инструкцию testb , чтобы проверить, можно ли использовать кучу. loadflags — это заголовок битовой маски, который определяется следующим образом:

и, как указано в протоколе загрузки:

Имя поля: loadflags

Это поле является битовой маской.

Бит 7 (запись): CAN_USE_HEAP
Установите этот бит равным 1, чтобы указать, что значение
heap_end_ptr допустимо. Если это поле пусто, будет отключена
часть функциональности установки.

Если установлен бит CAN_USE_HEAP , то в dx ставим значение heap_end_ptr (которое указывает на _end ) и добавляем к нему STACK_SIZE (минимальный размер стека 1024 байта). После этого переходим к метке 2 (как в предыдущем случае) и делаем правильный стек.


Нужны ещё два шага, прежде чем перейти к основному коду C: это настройка области BSS и проверка «волшебной» подписи. Сначала проверка подписи:


Инструкция просто сравнивает setup_sig с магическим числом 0x5a5aaa55. Если они не равны, сообщается о неустранимой ошибке.

Если магическое число совпадает и у нас есть набор правильных регистров сегментов и стек, то осталось лишь настроить раздел BSS перед переходом к коду C.

Раздел BSS используется для хранения статически выделенных неинициализированных данных. Linux тщательно проверяет, что эта область памяти обнулилась:


Первым делом начальный адрес __bss_start перемещается в di . Затем адрес _end + 3 (+3 для выравнивания по 4 байтам) перемещается в cx . Регистр eax очищается (с помощью инструкции xor ), вычисляется размер раздела bss ( cx-di ) и он помещается в cx . Затем cx делится на четыре (размер «слова») и многократно используется инструкция stosl , сохраняя значение еах (нуль) в адрес, указывающий на di , автоматически увеличивая di на четыре и повторяя это до тех пор, пока сх не достигнет нуля). Чистый эффект этого кода заключается в том, что нули записываются во все слова в памяти от __bss_start до _end :


Вот и всё: у нас есть стек и BSS, так что можно перейти к функции main() C:


Функция main() находится в arch/x86/boot/main.c. О ней поговорим в следующей части.

Это конец первой части об устройстве ядра Linux. Если у вас есть вопросы или предложения, свяжитесь со мной в твиттере, по почте или просто создайте тикет. В следующей части мы увидим первый код на C, который выполняется при установке ядра Linux, реализацию подпрограмм памяти, таких как memset , memcpy , earlyprintk , раннюю реализацию и инициализацию консоли и многое другое.

Здравствуйте, на ноутбуке стоял груб от opensuse, после обновления кали поставился ее груб вместо него, данный груб видит систему, но при входе в opensuse: «ошибка: «файл /vmlinuz-linux» не найден ошибка: сначала вам нужно загрузить ядро», кали нормально загружается


  1. Поставьте тег кали, не беспокойте занятых людей.
  2. Кали не предназначен для обычного использования. Велика вероятность того, что разработчики что-то да сломали в грабе.

Для загрузчика тоже есть корневая файловая система. Эта ФС, обычно прописывается в коде загрузчика, в загрузочный сектор или встроен в файл EFI образа загрузчика.

Если у тебя два раздела /boot, то для одного загрузчика будет и два / для загрузчиков разных систем.

В идеале /boot раздел должен быть один.

Самое простое это переместить файлы с образами ядра и initrd на одну файловую систему, далее переустановить загрузчик с этим /boot и обновить конфигурационны файл.

Постарайся с этим разобраться. Мне тебе далее объяснять лень. Ты как специоалист, раз используешь кали должен сам всё сделать.


Во вторых — обычно для загрузки grub2 должен загрузить файл с linux kernel и файл с initramfs, при этом передать им нужные параметры. Вот пример ручного конфига для grub2 из состава Debian для загрузки Arch в файле /etc/grub.d/40_custom :

Это простой пример конфига, при вынесенном /boot или LVM он иной, и параметры ядра отличаются от дистрибутива к дистрибутиву. Тебе нужно написать что-то подобное или разобраться, почему автоматически сгенерированный конфиг не работает. Вообще, я бы сделал grub2 от OpenSUSE главным, восстановив его через chroot, а для Kali бы написал простой конфиг руками — если бы вообще она была мне нужна, кроме пентестов этот дистрибутив ни для чего не пригоден.


Если есть флешка с сусей то загрузись с неё и там пункт загрузить линукс, выберешь сусю и в ясте загрузчик обнови

Желание пользоваться линуксом было давно,но считал,что не разберусь. Не так давно решил все же перейти на эту замечательную ОС, но на тот момент у меня был ноутбук Asus eee pc и как-то у меня с ним не очень вышло.(Пост ранее об этом писал) За прошедшее время обзавелся машинкой HP Elitebook 6930p и опять же решил поставить линукс. Сначала была установленна Lubuntu, но как-то не очень "зашла". После небольших раздумий решил,что стоит попробовать установить российскую ОС "Роса". Задуманно - сделанно. ROSA FRESH R11 установленна.

На следующий день,то бишь сегодня, решил чуть поэкспериментировать с драйверами видеокарты. В настройках на выбор было четыре драйвера(один как раз на данный момент использовался), выбрал другой наугад,применил, система запросила перезагрузку. И после оной - не загрузилась. Зато загрузился "веселый" черный экран. И что-то мне подсказывало, что это "Бзззззз" - неспроста.

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

текст гласил: "Поддерживается несколько BASH-подобных команд редактирования строки. Есть вывод списка команд по TAB для дополнения. Также есть везде, где возможно, вывод списка по TAB для устройств или файлов. "

Ну, и собсна,строка "grub> "

По логике вещей стало понятно,что похоже накрылось что-то в загрузчике GRUB. На тот момент я знал о загрузчке:

а) он загружает (что-то. Наверное,систему)

б) он называется GRUB

в) может загружать разные ОС

Все. Да и сейчас не рсбо больше знаю.

Первое решение обратиться за помощью в группу Росы в ВК - результатов не дало. Советы конечно дали, но в виде "чем смог - тем помог" . И за это спасибо!

Яндекс - выдал кучу всего. И все вроде понятно и просто, только вот нифига не срабатывает.

Методом проб и ошибок систему я запустил.

И поэтому выложу результаты опыта здесь - может кому сэкономлю время и нервы.

2) Восстановление загрузчика.

linux /boot/vmlinuz(здесь указываем полное название ядра,а не просто "vmlinuz") root=/dev/sdaY

initrd /boot/initrd(указываем соответственно ядру, и опять же полное название включая расширение)

Те кто шпаргалку не понял. листайте ниже. там объяснения и фото.

Первое что пишем это - ls.

Эта команда возвратит известные диски и разделы.

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Далее пользователь должен задать диск и раздел, где находиться система. Если вы не помните/не знаете, где она, то методом научного тыка перебираете все. По очереди. Из тех вариантов, что вам вернула команда ls. То есть в моем случае это было так

ls (hd0,1) <--Приставку msdos можно опустить--->

На вариантах hd0,5 и hd0,1 команда выдала, что на данных разделах имеется файловая система ext. Значит на одном из них и должна находиться наша система.

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Проверить можно также командой ls. Добавив после раздела слэш.

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Команда возвратила название каталогов (папок) находящихся на этом разделе. Среди них есть каталог Boot, который нам и нужен.

Но еще неплохо бы узнать какой именно загрузчик у нас. GRUB или GRUB2. Каталог должен находиться в Boot, поэтому вновь воспользуемся командой ls немного ее дополнив

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Тут мы видим каталог grub2, а также видим два ядра(vmlinuz) и два файла initrd соответствующих ядрам. Это очень нужная информация!

Дальше мы, используя команду set prefix, устанавливаем префикс и корневой раздел

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Указываем путь к файловой системе

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

загружаем модуль загрузки linux

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Теперь нам надо загрузить ядро. У меня их почему-то два. Выбирал наугад.

linux /boot/vmlinuz-4.15.0-desktop-47.2rosa-x86_64 root=/dev/sda1

В конце обязательно указываем root-раздел

В интернетике пишут,что полное название ядра можно не указывать. Можно ограничиться записью вида:

Но у меня почему-то такой вариант не проходил ни в какую. До тех пор пока не указал имя ядра полностью. Может из-за того,что ядра два?!

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Теперь выбираем образ инит-диска(еще б мне кто объяснил что такое вообще)

образ инит-диска выбираем соответсвенно ядру. Обратите внимание,что у инит-диска указывается расширение файла - .img .

Указывают, что выбор инит-диска можно записать короче

У меня такой вариант не прошел.

GRUB2. Восстановление. Запуск системы. Linux, Grub2, Команды linux, Длиннопост

Ну-с и последнее. загрузка.

Если все сделали правильно - будет вам счастье!

Понимание процедуры загрузки в Linux RHEL7/CentOS

Следующие шаги суммируют, как процедура загрузки происходит в Linux.

1. Выполнение POST: машина включена. Из системного ПО, которым может быть UEFI или классический BIOS, выполняется самотестирование при включении питания (POST) и аппаратное обеспечение, необходимое для запуска инициализации системы.

2. Выбор загрузочного устройства: В загрузочной прошивке UEFI или в основной загрузочной записи находится загрузочное устройство.

3. Загрузка загрузчика: с загрузочного устройства находится загрузчик. На Red Hat/CentOS это обычно GRUB 2.

4. Загрузка ядра: Загрузчик может представить пользователю меню загрузки или может быть настроен на автоматический запуск Linux по умолчанию. Для загрузки Linux ядро загружается вместе с initramfs . Initramfs содержит модули ядра для всего оборудования, которое требуется для загрузки, а также начальные сценарии, необходимые для перехода к следующему этапу загрузки. На RHEL 7/CentOS initramfs содержит полную операционную систему (которая может использоваться для устранения неполадок).

5. Запуск /sbin/init: Как только ядро загружено в память, загружается первый из всех процессов, но все еще из initramfs . Это процесс /sbin/init , который связан с systemd . Демон udev также загружается для дальнейшей инициализации оборудования. Все это все еще происходит из образа initramfs .

6. Обработка initrd.target: процесс systemd выполняет все юниты из initrd.target , который подготавливает минимальную операционную среду, в которой корневая файловая система на диске монтируется в каталог /sysroot . На данный момент загружено достаточно, чтобы перейти к установке системы, которая была записана на жесткий диск.

7. Переключение на корневую файловую систему: система переключается на корневую файловую систему, которая находится на диске, и в этот момент может также загрузить процесс systemd с диска.

8. Запуск цели по умолчанию (default target): Systemd ищет цель по умолчанию для выполнения и запускает все свои юниты. В этом процессе отображается экран входа в систему, и пользователь может проходить аутентификацию. Обратите внимание, что приглашение к входу в систему может быть запрошено до успешной загрузки всех файлов модуля systemd . Таким образом, просмотр приглашения на вход в систему не обязательно означает, что сервер еще полностью функционирует.
На каждом из перечисленных этапов могут возникнуть проблемы из-за неправильной настройки или других проблем. Таблица суммирует, где настроена определенная фаза и что вы можете сделать, чтобы устранить неполадки, если что-то пойдет не так.

Передача аргементов в GRUB 2 ядру во время загрузки

Если сервер не загружается нормально, приглашение загрузки GRUB предлагает удобный способ остановить процедуру загрузки и передать конкретные параметры ядру во время загрузки. В этой части вы узнаете, как получить доступ к приглашению к загрузке и как передать конкретные аргументы загрузки ядру во время загрузки.

Когда сервер загружается, вы кратко видите меню GRUB 2. Смотри быстро, потому что это будет длиться всего несколько секунд. В этом загрузочном меню вы можете ввести e, чтобы войти в режим, в котором вы можете редактировать команды, или c, чтобы ввести полную командную строку GRUB.


После передачи e в загрузочное меню GRUB вы увидите интерфейс, показанный на скриншоте ниже. В этом интерфейсе прокрутите вниз, чтобы найти раздел, начинающийся с linux16 /vmlinuz , за которым следует множество аргументов. Это строка, которая сообщает GRUB, как запустить ядро, и по умолчанию это выглядит так:



После ввода параметров загрузки, которые вы хотите использовать, нажмите Ctrl + X, чтобы запустить ядро с этими параметрами. Обратите внимание, что эти параметры используются только один раз и не являются постоянными. Чтобы сделать их постоянными, вы должны изменить содержимое файла конфигурации /etc/default/grub и использовать grub2-mkconfig -o /boot/grub2/grub.cfg , чтобы применить изменение.

Когда у вас возникли проблемы, у вас есть несколько вариантов (целей), которые вы можете ввести в приглашении загрузки GRUB:

■ rd.break Это останавливает процедуру загрузки, пока она еще находится в стадии initramfs .
Эта опция полезна, если у вас нет пароля root.

■ init=/bin/sh или init=/bin/bash Указывает, что оболочка должна быть запущена сразу после загрузки ядра и initrd . Это полезный вариант, но не лучший, потому что в некоторых случаях вы потеряете консольный доступ или пропустите другие функции.

■ systemd.unit=rescue.target Команда запускает еще несколько системных юнитов, чтобы привести вас в более полный рабочий режим. Требуется пароль root.
Чтобы увидеть, что загружено только очень ограниченное количество юнит-файлов, вы можете ввести команду systemctl list-units .

Запуск целей(targets) устранения неполадок в Linux

1. (Пере)загружаем Linux. Когда отобразиться меню GRUB, нажимаем e ;

2. Находим строку, которая начинается на linux16 /vmlinuz. В конце строки вводим systemd.unit=rescue.target и удаляем rhgb quit ;

3. Жмем Ctrl+X, чтобы начать загрузку с этими параметрами. Вводим пароль от root;

4. Вводим systemctl list-units и смотрим. Будут показаны все юнит-файлы, которые загружены в данный момент и соответственно загружена базовая системная среда;

5. Вводим systemctl show-environment . Видим переменные окружения в режиме rescue.target;

6. Перезагружаемся reboot ;

7. Когда отобразится меню GRUB, нажимаем e . Находим строку, которая начинается на linux16 /vmlinuz. В конце строки вводим systemd.unit=emergency.target и удаляем rhgb quit ;

8. Снова вводим пароль от root;

9. Система загрузилась в режиме emergency.target;

10. Вводим systemctl list-units и видим, что загрузился самый минимум из юнит-файлов.

Устранение неполадок с помощью загрузочного диска Linux

Еще один способ восстановления работоспособности Linux использовать образ операционки.

Если вам повезет меньше, вы увидите мигающий курсор в системе, которая вообще не загружается. Если это произойдет, вам нужен аварийный диск. Образ восстановления по умолчанию для Linux находится на установочном диске. При загрузке с установочного диска вы увидите пункт меню "Troubleshooting". Выберите этот пункт, чтобы получить доступ к параметрам, необходимым для ремонта машины.

  • Install CentOS 7 in Basic Graphics Mode: эта опция переустанавливает систему. Не используйте её, если не хотите устранить неполадки в ситуации, когда обычная установка не работает и вам необходим базовый графический режим. Как правило, вам никогда не нужно использовать эту опцию для устранения неисправностей при установке.
  • Rescue a CentOS System: это самая гибкая система спасения. Это должен быть первый вариант выбора при использовании аварийного диска.
  • Run a Memory Test: если вы столкнулись с ошибками памяти, это позволяет пометить плохие микросхемы памяти, чтобы ваша машина могла нормально загружаться.
  • Boot from local drive: здесь я думаю всё понятно.

Пример использования "Rescue a CentOS System"

1. Перезагружаем сервер с установочным диском Centos 7. Загружаемся и выбираем "Troubleshooting".

2. В меню траблшутинга выбираем "Rescue a CentOS System" и загружаемся.


3. Система восстановления теперь предлагает вам найти установленную систему Linux и смонтировать ее в /mnt/sysimage . Выберите номер 1, чтобы продолжить:
4. Если была найдена правильная установка CentOS, вам будет предложено, чтобы система была смонтирована в /mnt/sysimage . В этот момент вы можете дважды нажать Enter, чтобы получить доступ к оболочке восстановления.



5. Ваша система Linux на данный момент доступна через каталог /mnt/sysimage . Введите chroot /mnt/sysimage . На этом этапе у вас есть доступ к корневой файловой системе, и вы можете получить доступ ко всем инструментам, которые необходимы для восстановления доступа к вашей системе.

Переустановка GRUB с помощью аварийного диска

Одна из распространенных причин, по которой вам нужно запустить аварийный диск, заключается в том, что загрузчик GRUB 2 не работает. Если это произойдет, вам может понадобиться установить его снова. После того, как вы восстановили доступ к своему серверу с помощью аварийного диска, переустановить GRUB 2 несложно, и он состоит из двух этапов:

  1. Убедитесь, что вы поместили содержимое каталога /mnt/sysimage в текущую рабочую среду.
  2. Используйте команду grub2-install , а затем имя устройства, на котором вы хотите переустановить GRUB 2. Если это виртуальная машина KVM используйте команду grub2-install /dev/vda и на физическом сервере или виртуальная машина VMware, HyperV или Virtual Box, это grub2-install /dev/sda .

Повторное создание Initramfs с помощью аварийного диска

Иногда initramfs также может быть поврежден. Если это произойдет, вы не сможете загрузить свой сервер в нормальном рабочем режиме. Чтобы восстановить образ initramfs после загрузки в среду восстановления, вы можете использовать команду dracut . Если используется без аргументов, эта команда создает новый initramfs для загруженного в данный момент ядра.
Кроме того, вы можете использовать команду dracut с несколькими опциями для создания initramfs для конкретных сред ядра. Существует также файл конфигурации с именем /etc/dracut.conf , который можно использовать для включения определенных параметров при повторном создании initramfs .

  • /usr/lib/dracut/dracut.conf.d/*.conf содержит системные файлы конфигурации по умолчанию.
  • /etc/dracut.conf.d содержит пользовательские файлы конфигурации dracut.
  • /etc/dracut.conf используется в качестве основного файла конфигурации.

Исправление общих проблем

В пределах статьи, подобной этой, невозможно рассмотреть все возможные проблемы, с которыми можно столкнуться при работе с Linux. Однако есть некоторые проблемы, которые встречаются чаще, чем другие. Ниже некоторые наиболее распространенные проблемы.

Переустановка GRUB 2

Код загрузчика не исчезает просто так, но иногда может случиться, что загрузочный код GRUB 2 будет поврежден. В этом случае вам лучше знать, как переустановить GRUB 2. Точный подход зависит от того, находится ли ваш сервер в загрузочном состоянии. Если это так, то довольно просто переустановить GRUB 2. Просто введите grub2-install и имя устройства, на которое вы хотите его установить. У команды есть много различных опций для точной настройки того, что именно будет установлено, но вам, вероятно, они не понадобятся, потому что по умолчанию команда устанавливает все необходимое, чтобы ваша система снова загрузилась. Становится немного сложнее, если ваш сервер не загружается.

Если это произойдет, вам сначала нужно запустить систему восстановления и восстановить доступ к вашему серверу из системы восстановления. После монтирования файловых систем вашего сервера в /mnt/sysimage и использования chroot /mnt/sysimage , чтобы сделать смонтированный образ системы вашим корневым образом: Просто запустите grub2-install , чтобы установить GRUB 2 на желаемое установочное устройство. Но если вы находитесь на виртуальной машине KVM, запустите grub2-install /dev/vda , а если вы находитесь на физическом диске, запустите grub2-install /dev/sda .

Исправление Initramfs

В редких случаях может случиться так, что initramfs будет поврежден. Если вы тщательно проанализируете процедуру загрузки, вы узнаете, что у вас есть проблема с initramfs , потому что вы никогда не увидите, как корневая файловая система монтируется в корневой каталог, и при этом вы не увидите запуска каких-либо системных модулей. Если вы подозреваете, что у вас есть проблема с initramfs , ее легко создать заново. Чтобы воссоздать его, используя все настройки по умолчанию (что в большинстве случаев нормально), вы можете просто запустить команду dracut --force . (Без --force команда откажется перезаписать ваши существующие initramfs .)
При запуске команды dracut вы можете использовать файл конфигурации /etc/dracut.conf , чтобы указать, что именно записывается в initramfs . В этом файле конфигурации вы можете увидеть такие параметры, как lvmconf = «no» , которые можно использовать для включения или выключения определенных функций. Используйте эти параметры, чтобы убедиться, что у вас есть все необходимые функции в initramfs .

Восстановление после проблем с файловой системой

Читайте также: