Вопрос или проблема
Я пытаюсь использовать метки разделов (или UUID, что не имеет значения), чтобы выбрать корневой раздел без использования initrd/initramfs.
С initramfs это довольно просто: root=LABEL=...
или root=/dev/disk/by-label/...
в аргументах ядра выполняет задачу. Однако без initramfs это невозможно: нотация LABEL=
декодируется скриптом initramfs, а символические ссылки /dev/disk/by-label/...
создаются udev, работающим из initramfs. Только нотация root=/dev/sdXY
понимается самим ядром.
Тем не менее, GRUB поддерживает скрипты в стиле командной оболочки, и я думаю, что это может быть реализовано в виде скрипта GRUB 2, который будет генерировать строку root=/dev/sdXY
из метки устройства или UUID.
В частности, команда search --label <label> --set ROOTDEV
установит переменную ROOTDEV
со строкой вроде hd0,gpt5
, которая указывает на раздел с заданной меткой. Если я правильно понимаю (пожалуйста, исправьте меня, если я ошибаюсь), порядок устройств в GRUB и ядре одинаковый, так что hd0
это /dev/sda
, hd1
это /dev/sdb
и так далее.
Так что вот вопрос: есть ли способ, изнутри скрипта GRUB 2, преобразовать hd0,gpt5
в /dev/sda5
? Именно часть hd0
в sda
– остальное легко сделать с помощью регулярных выражений.
Когда Grub2 находится на USB-накопителе (на этом USB-накопителе не установлена Linux, поэтому grub.cfg должен быть создан и отредактирован вручную), литерал раздела данных меняется в зависимости от количества подключенных внутренних и внешних устройств, а также от того, загружается ли оборудование в режимах UEFI или BIOS.
В некоторых строках мне нужно иметь параметр в форме /dev/sd$#, не в стиле GRUB, он должен указывать на такие данные раздела (литерал не всегда одинаковый, это сильно зависит от компьютера, с которого я загружаю такой USB).
С помощью команды поиска GRUB я могу получить литерал, но в стиле GRUB.
Я не знаю, как использовать регулярные выражения внутри файла grub.cfg, чтобы заменить hd# на sd$, а также чтобы заменить ‘,msdos#’ или ‘,gpt#’ на #.
Возможно, ссылка на регулярные выражения в grub.cfg будет полезной.
Ответ или решение
Для решения задачи конвертации имен устройств в обозначение GRUB и обратно, необходимо учитывать две главные детали: правильное использование команд GRUB и возможность манипуляции строками в GRUB 2. Таким образом, мы можем создать скрипт, который будет выполнять вашу задачу.
Шаг 1: Использование команды search
Как вы правильно отметили, вы можете использовать команду search
для нахождения устройства по метке. Пример команды:
search --label <your_label> --set ROOTDEV
После выполнения этой команды переменная ROOTDEV
будет содержать значение в формате hdX,gptY
или hdX,msdosY
, в зависимости от типа разметки.
Шаг 2: Конвертация GRUB обозначения в Linux обозначение
Теперь, чтобы преобразовать строку вида hd0,gpt5
в строку /dev/sda5
, нам нужно будет выделить определенные части строки. В GRUB нет поддержки регулярных выражений в том виде, как это реализовано в некоторых других языках программирования, но мы можем воспользоваться простыми строковыми операциями.
Шаг 3: Пример скрипта
Ниже приведен пример скрипта, который поможет вам преобразовать hdX
в sdX
, а также удалить ,gpt#
или ,msdos#
:
# Поиск устройства по метке
search --label <your_label> --set ROOTDEV
# Получаем строку из переменной ROOTDEV
set GRUB_DEV=${ROOTDEV}
# Разделение строки на устройство и номер
set DEVICE_PART=${GRUB_DEV%%,*} # Получаем hd0
set PARTITION=${GRUB_DEV##*,} # Получаем gpt5
# Конвертация hdX в sdX
set DEVICE_NUM=${DEVICE_PART#hd} # Убираем hd
set DEVICE_NAME=s${DEVICE_NUM} # Подставляем s
# Формирование окончательного имени устройства
set FINAL_DEVICE=${DEVICE_NAME}${PARTITION}
echo "Linux device name: /dev/${FINAL_DEVICE}"
Объяснение кода
- Нахождение устройства: Сначала мы ищем устройство по метке и сохраняем его в переменной
ROOTDEV
. - Разделение переменной: Используем простые операции для получения имени устройства и номера раздела.
- Конвертация: Изменяем
hdX
наsdX
, при этом принимаем во внимание различия в обозначениях. - Формирование имени: Собираем полное имя устройства, добавляя номер раздела.
Примечания
- Обратите внимание, что порядок устройств в GRUB и в Linux должен совпадать. Обычно
hd0
соответствует/dev/sda
,hd1
— это/dev/sdb
и так далее. - В зависимости от конфигурации вашего оборудования и порядка загрузки может потребоваться дополнительная настройка, чтобы гарантировать правильность работы скрипта.
Заключение
Используя предложенный подход, вы сможете динамически генерировать имена устройств в нужном формате. Это решение позволяет вам обойти ограничение, связанное с отсутствием инициализации RAM-диска и использовать метки или UUID для загрузки нужной системы. Убедитесь, что вы тестируете конфигурацию на разных устройствах, чтобы гарантировать ее стабильность и правильность.