Преобразование имени раздела и устройства в формат SYSLINUX
Меня спрашивают, а где на практике можно применить "номер буквы в алфавите", про получение которого в bash-скрипте было недавно написано. Вот пример такого практического применения. Известно, что в Linux дисковые устройства представлены в виде
/dev/sda, /dev/sdb, /dev/sdc и т.д., а разделы диска в виде /dev/sda1, /dev/sda2...SYSLINUX, точнее его модуль
chain.c32, который может передавать управление другим загрузчикам, использует другой формат: hdD Pгде:
D - номер устройства (диска) в BIOSP - номер раздела на дискеОтсчет дисков ведется с 0, разделов - с 1 (0 - главная загрузочная запись диска)
Например,
hd0 2 - загрузка должна производиться со 2 раздела первого диска, hd1 1 - с 1 раздела второго жесткого диска, hd3 0 - необходимо передать управление главной загрузочной записи (MBR) четвертого диска.Вот часть конфига
syslinux.cfg, где chainloading используется для загрузки Windows со второго раздела на первом жестком диске:LABEL windows
menu label Microsoft Windows 7
kernel modules/chain.c32
append hd0 2
- Минус, связанный с BIOS. Если вдруг порядок устройств в BIOS поменяется, то загрузчик SYSLINUX "заблудится" и попытается передать управление не туда.
- Некоторые линуксы меняют порядок именования жестких дисков, т.е.
/dev/hda может и не соответствовать первому загрузочному диску. Тут уже зависит от конкретного дистрибутива.Первый минуса можно избежать, используя вместо номера диска MBR ID, но это уже тема для отдельной заметки.
chain.c32Я организовал это в отдельной функции
get_sysl_hd(), чтобы было удобно утащить в другой скрипт, буде понадобится. Первый параметр функции - имя устройства, например, /dev/sda11. Получаем имя устройства без пути к нему.
T_DN=`basename $1`2. Можно проверить, соответствует ли имя устройства формату имени дисков, а то вдруг нам CD-ROM подсунули :)
Имя диска начинается с первой буквы
s или h на некоторых пожилых дистрибутивах, далее следует буква d, далее - латинская буква a-z, потом могут следовать цифры (номера разделов). Можно сообразить вот такое простенькое регулярное выражение:^[sh]d[a-z][1-9]*$Далее пропускаем результат работы
basename через grep, и проверяем выхлоп в переменной. Если переменная пустая, подсунули что-то не то.T_DN=`basename $1|grep '^[sh]d[a-z][1-9]*$'`
if [ -z "$T_DN" ]; then
return 1
fi
Но на самом деле, эта проверка не очень-то и нужна, можно пропустить этот пункт
3. Получаем третью букву в имени диска с помощью команды
expr:expr substr pos lenгде:
substr - операция получения подстрокиpos - позиция символа в строке (отсчет ведется с единицы)len - длина подстрокиT_3LET=`expr substr $T_DN 3 1`4. Получаем номер буквы в алфавите. Я воспользовался вторым копия из ранее описанных способов.
S_CODE=`printf '%d' \'$T_3LET`
A_CODE=`printf '%d' \'a`
SYSL_ID="hd"`expr $S_CODE - $A_CODE`5. Получим номер раздела, удалив
sed'ом все латинские буквы с начала имени устройства в переменной $T_DN:T_VOLNUM=`echo "$T_DN" | sed 's/^[a-z]*//'`
if [ -z "$T_VOLNUM" ]; then
T_VOLNUM=0
fi
Если переменная окажется пустой, значит нам подсунули устройство, без указания раздела - необходимо сослаться на MBR. Присваиваем
T_VOLNUM значение 0.6. Добавляем полученные данные в переменную
SYSL_IDSYSL_ID="$SYSL_ID $T_VOLNUM"7. Пример вызова функции:
if [ -z "$1" ]; then
echo "Use "`basename $0` "<device>"
exit
fi
get_sysl_hd "$1"
if [ $? -ne 0 ];then
echo "Bad device name!"
else
echo "$1: $SYSL_ID"
fiНа PasteBin
На GitHub
1. Syslinux (Русский)
2. Работа со строками
3. BASH: Получить номер буквы в латинском алфавите, более элегантное решение. Копия
Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2019/06/15/preo