а зачем постоянно обновлять конфигурационный файл grub?
Ядра. Если подразумевается пропуск и "своеобзывание" операционок на основе ядра linux, которые еще и предполагается в итоге обновлять (две и более убунт на одном харде в разных разделах, к примеру), то автоподготовка загрузчика очень актуальна, так что вопрос считаю правильным, - сам в свое время им задавался.
Неужели нельзя в GRUB2 менять названия строк меню навсегда?
Можно. И даже предлагаю не /etc/grub.d/40_custom, а какой-нибудь самопальный 11_custom по тому же пути (чем ниже число, тем выше пункт оказывается в меню GRUB2; если что-то все же остается через os-prober, то следует понимать что os_prober хранится в 30_os-prober, а значит надо брать ниже 30. Первая строка (которая Ubutnu) формируется файлом 10_linux, поэтому обозвав файл 11_custom - впишем его в аккурат после первой строки. Допустим, имеем дуалбут. И допустим, в этом дуалбуте у нас Windows 7 (пишу для своего примера, но общий принцип един).
1. Смотрим как сейчас загружается windows. Например, так [пример команды, вероятно, притянут за уши (не факт что будет именно 10 строк), но в общем случае ищем пункт меню, который нас названием не устраивает, и смотрим его начинку между знаками { и } (я их сделал красным шрифтом в этой цитате)]:
cat /boot/grub/grub.cfg | grep -i windows -A10
В ответ я вижу:
menuentry 'Windows Boot Manager (на /dev/sda1)' --class windows --class os $menuentry_id_option 'osprober-efi-81AE-22EB' {
insmod part_gpt
insmod fat
set root='hd0,gpt1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 81AE-22EB
else
search --no-floppy --fs-uuid --set=root 81AE-22EB
fi
chainloader /EFI/microsoft/boot/bootmgfw.efi
}
В сущности, поскольку Windows мы двигать никуда не собираемся, - достаточно просто данный текст (с измененным не устраивающим нас именем, которое выделено жирным) внести в соответствующий файл - и груб будет успешно грузить винду оттуда.
2. Выполняем
gedit ~/11_custom
Заполняем файл таким образом:
#!/bin/sh
exec tail -n +3 $0
#Мой кастомный пункт загрузки Windows7. Верхние строчки менять нельзя, - благодаря ним все прочее в этом файле после update-grub в неизменном виде попадет в файл grub.cfg
#Строчкой ниже вставляем видозимененный текст из п.1:
menuentry 'Windows 7 Ultimate Edition' --class windows --class os $menuentry_id_option 'osprober-efi-81AE-22EB' {
insmod part_gpt
insmod fat
set root='hd0,gpt1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 81AE-22EB
else
search --no-floppy --fs-uuid --set=root 81AE-22EB
fi
chainloader /EFI/microsoft/boot/bootmgfw.efi
}
Сохраняем полученный файл. Далее перемещаем его в правильную для него директорию:
sudo mv ~/11_custom /etc/grub.d/11_custom
(почему не применяю сразу sudo gedit: сталкивался с тем, что на 18.04 это уже не работает, - потому и привожу способ, который должен сработать вне зависимости от версии Ubuntu).
Варинтов на момент написания поста три. Два моих - хромых. Один я когда-то
подглядел у уважаемого
andytux, за что ему, пользуясь случаем, большущее спасибо. Сперва свои хромые.
Содержимое файла 11_custom в этом случае будет таким:#!/bin/sh
exec tail -n +3 $0
menuentry "Windows 7 Ultimate Edition (или что у Вас там за версия)" --class windows --class os {
exit
}
И таки-да: тупо выход. Подразумевается, что следующим пунктом загрузки в BIOS у Вас выставлена Windows, - тогда, покидая груб, машина наткнется на неё. Дёшево и сердито.
Выясняем UUID раздела. Для этого выполняем в терминале команду
grub-probe --target=fs_uuid /boot/*/*/microsoft/boot/bootmgfw.efi
В выхлопе должен быть UUID, например 81AE-22EB. Если его не получили по каким-то причинам - выполняем
sudo blkid | grep fat
(почему-то всякий раз грепая по ключевому слову fat я вижу перед глазами
это) Ответом будет сегмент вида UUID="81AE-22EB". Содержимое файла 11_custom в этом случае будет таким:
#!/bin/sh
exec tail -n +3 $0
menuentry "Windows 7 Ultimate Edition (или что у Вас там за версия)" --class windows --class os {
insmod part_gpt
insmod fat
search --fs-uuid --no-floppy --set=root 81AE-22EB
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}
Ясное дело вместо 81AE-22EB вставляем свой, найденный по выхлопу команд выше UUID
Содержимое файла 11_custom в этом случае будет таким:#!/bin/sh
exec tail -n +3 $0
menuentry "Windows 7 Ultimate Edition (или что у Вас там за версия)" --class windows --class os {
src='/Windows/System32/winload'
root='x'
if [ ${grub_platform} = efi ]
then msg="$msg EFI"; avload='chainloader'
src="${src}.efi"
src='/EFI/bootmgfw.efi'
insmod part_gpt
insmod fat
search -n -s -f ${src}
else avload='ntldr'
src='/bootmgr'
insmod part_msdos
insmod ntfs
search -n -s -f ${src}
if [ $root = x ]
then src='/ntldr'
search -n -s -f ${src}
if [ $root = x ]
then src='/MSDOS.SYS'
insmod fat
search -n -s -f ${src}
if [ $root = x ]
then src='/I386/SETUPLDR.BIN'
# insmod iso9660
# insmod udf
search -n -s -f ${src}
if [ $root = x ]
then src='/BCDW/LOADER.BIN'
search -n -s -f ${src}
if [ $root = x ]
then src='/opt/avndos.img'
search -n -s -f ${src}
if [ $root = x ]
then src='Windows'
else avinit="initrd16 $src"; avload='linux16'; src='/boot/syslinux/memdisk ima raw'
fi
fi
fi
else src='+1'
drivemap -s (hd0) ${root}
fi
fi
fi
if [ "$src" = "+1" ]; then avload='chainloader'; else insmod ${avload}; fi
fi
if [ $root = x ]
then msg="$src not exist!"
else msg="Load $src from $root"
fi
echo "$msg"; sleep -v 4
if [ -n "$avload" ]; then ${avload} ${src}; fi
if [ -n "${avinit}" ]; then ${avinit}; fi
}
3. Наш правильный файл находится в правильном месте. Самое время выполнить его добавление в меню:
sudo update-grub
Перезагружаемся. В меню GRUB2 видим два пункта, загружающих Windows. Только один из них - тот, что мы хотим, а второй - тот что нас не устраивал. Но работают ОБА (желательно проверить факт загрузки, дабы исключить всяческую возможность своей ошибки, и не плодить после темы из серии grub не видит windows).
4. Загружаемся в Ubuntu. Теперь будем прятать первый пункт, который нас не устраивал. Редактировать придется файл
sudo gedit /etc/default/grub #это для 16.04 и ниже
SUDO_EDITOR=gedit sudoedit /etc/default/grub #это для 18.04 и выше
Проверяем: есть ли в наличии в файле параметр GRUB_OS_PROBER_SKIP_LIST. Если нет, - дописываем, если есть - корректируем существующий. Он может быть закомментирован знаком канделла # в начале строки (знак убрать, параметр оставить). Вношу в него в рассматриваемом случае такой текст:
GRUB_OS_PROBER_SKIP_LIST="81AE-22EB@/EFI/microsoft/boot/bootmgfw.efi"
Что есть что и почему именно так. Ранее приводил код загрузки, - там есть подчеркнутый текст и текст, отмеченный курсивом. Подчеркнутый - это UUID раздела, на котором находится подгружаемый бинарник. А курсивная часть - это полный путь относительно этого раздела к самому бинарнику, который груб должен подгрузить. В общем случае в параметре GRUB_OS_PROBER_SKIP_LIST приходится указывать именно такие пары: UUID@[что_пропускать]. После того как внесли данный параметр (адаптированный под свой случай, а не тупо перекопировав то, что я написал), - можно запускать
sudo update-grub
В выхлопе команды мы, среди прочего, увидем что-то типа "Skipped Windows Boot Manager (на /dev/sda1)". Если такое обнаружили - можно довольно ухмыльнуться и перезагрузиться. При загрузке мы будем видеть только наш кастомный созданный ручками пункт. И каждый раз при последующих вызовах update-grub имя будет прописываться корректно, и без заскоков.
В случае с Windows все относительно просто и понятно, и в документации grub явным образом прописано. Однако в случае с linux все несколько иначе. Вот рабочий вариант параметров:
81AE-22EB@/EFI/microsoft/boot/bootmgfw.efi - Windows 7 (ссылка на efi-файл на efi-разделе, общем для всех систем)
a336ca06-f73f-4a87-9958-6928d844bbf9@/dev/sda4 - Linux (ссылка на раздел на жестком диске, где установлен конкретный linux-дистрибутив)
Вариант комбинирования нескольких записей, чтобы пропускалась не одна операционка, а несколько:
GRUB_OS_PROBER_SKIP_LIST="81AE-22EB@/EFI/microsoft/boot/bootmgfw.efi a336ca06-f73f-4a87-9958-6928d844bbf9@/dev/sda4 54b15982-7c66-40a6-88c5-2167fc189114@/dev/sda5"
Ну и относительно ядер. Раз уж заикнулся. Ранее создавал скрипт, публиковал его
здесь. Там происходит автоподстановка текущей актуальной версии ядра, а также имени операционной системы и прочего... По аналогии с этим можно в файл 11_custom поместить такой вот код:
#! /bin/bash
set -e
# Скрипт для автоматизации добавления в загрузчик GRUB2
# строки с возможностью запуска системы.
# При update-grub замена необходимых переменных выполняется автоматически.
# ! подготовлено для UEFI, на Legacy не испытывалось !
wheremount=$(mount | grep "on / ") #куда смонтирован корневой каталог
sysdisk=${wheremount%%\ *} #имя системного диска, напр. /dev/sda1
sysdiskGF=${sysdisk//\/dev\//} #выбрасываем /dev/
sysdiskGF=$(echo $sysdiskGF | sed -e 's/[0-9]/gpt\0/g') #заменяем sda1 -> sda,gpt1
#выполняем замену "sda" -> "hd0," - тупо, но работает...
sysdiskGF=$(echo $sysdiskGF | sed -e 's/sda/hd0,/g;s/sdb/hd1,/g;s/sdc/hd2,/g;s/sdd/hd3,/g;s/sde/hd4,/g;s/sdf/hd5,/g;s/sdg/hd6,/g;s/sdh/hd7,/g;s/sdi/hd8,/g;s/sdj/hd9,/g;s/sdk/hd10,/g;s/sdl/hd11,/g;s/sdm/hd12,/g;s/sdn/hd13,/g;s/sdo/hd14,/g;s/sdp/hd15,/g;s/sdq/hd16,/g;s/sdr/hd17,/g;s/sds/hd18,/g;s/sdt/hd19,/g;s/sdu/hd20,/g;s/sdv/hd21,/g;s/sdw/hd22,/g;s/sdz/hd23,/g;s/sdy/hd24,/g;s/sdz/hd25,/g')
#на выходе имеем в sysdiskGF hd0,gpt1
#получаем UUID диска:
root_uuid=$(blkid | grep $sysdisk)
root_uuid=$(echo $root_uuid | sed -e 's/^.*\ UUID=\"//' -e 's/\".*//')
#получаем актуальное ядро vmlinuz:
cur_vmlinuz=$(echo `ls -l /vmlinuz` | sed 's/.*->\ //')
#получаем актуальный RAM-диск initrd:
cur_initrd=$(echo `ls -l /initrd.img` | sed 's/.*->\ //')
echo "menuentry 'Мой Linux дистрибутив, который называется так, как я хочу' --class ubuntu --class gnu-linux --class gnu --class os \$menuentry_id_option 'ubuntu-single-mode-cur-kernel' {"
echo " recordfail"
echo " load_video"
echo " gfxmode \$linux_gfx_mode"
echo " insmod gzio"
echo " if [ x\$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi"
echo " insmod part_gpt"
echo " insmod ext2"
echo " set root='$sysdiskGF'"
echo " if [ x\$feature_platform_search_hint = xy ]; then"
echo " search --no-floppy --fs-uuid --set=root --hint-bios=$sysdiskGF --hint-efi=$sysdiskGF --hint-baremetal=${sysdiskGF/hd/ahci} $root_uuid"
echo " else"
echo " search --no-floppy --fs-uuid --set=root $root_uuid"
echo " fi"
echo " linux $cur_vmlinuz root=UUID=$root_uuid ro \$vt_handoff"
echo " initrd $cur_initrd"
echo "}"
Сработает, если мы хотим "переименовать" ту самую строку "Ubuntu". Установленные на соседних разделах по отношению к текущему дистрибутивы данный скрипт не подгрузит - его нужно править. В сущности, привожу для примера, т.к. под конкретный случай писать придется все равно на месте.
Сам сейчас живу на refind, в котором отключил автопоиск операционок на диске, и в файле применяемой темы прописал:menuentry "Ubuntu 16.04 x64" {
icon /EFI/refind/next-theme/icons/os_ubuntu.png
volume UbuntuUNITY16.04
loader /vmlinuz
initrd /initrd.img
options "root=UUID=987233ee-3155-49cf-a30b-d342f7c0bf88 ro"
submenuentry "Boot with NOMODESET" {
add_options "nomodeset"
}
submenuentry "Boot into Single-mode" {
add_options "single"
}
}
menuentry "Ubuntu Budgie 18.04 x64" {
icon /EFI/refind/next-theme/icons/os_ubuntubudgie.png
volume UbuntuBudgie18.0
loader /vmlinuz
initrd /initrd.img
options "root=UUID=c7de65c9-6ed5-4526-929b-3f6b7ab03789 ro"
submenuentry "Boot with NOMODESET" {
add_options "nomodeset"
}
submenuentry "Boot into Single-mode" {
add_options "single"
}
}
menuentry "KUbuntu 18.04 x64" {
icon /EFI/refind/next-theme/icons/os_kubuntu.png
volume KUbuntu18.04
loader /vmlinuz
initrd /initrd.img
options "root=UUID=f3333854-a286-4604-a2a5-968aca779d05 ro"
submenuentry "Boot with NOMODESET" {
add_options "nomodeset"
}
submenuentry "Boot into Single-mode" {
add_options "single"
}
}
menuentry "WiFi SLAX 1.1 x64" {
icon /EFI/refind/next-theme/icons/wifislax.png
volume wifislax64-1.1
loader /boot/vmlinuz-4.9.40-wifislax64
options "root=PARTUUID=335aa891-4740-4a97-9c56-ab811b5a4c2c ro nomodeset"
}
menuentry "Windows 7 ULTIMATE x64" {
icon /EFI/refind/next-theme/icons/windows.png
loader /EFI/Microsoft/Boot/bootmgfw.efi
}
Для чего привожу: как видно из кода, применяются сами символьные ссылки, а не выдергивание из них информации о том, куда они ссылаются. Нет возможности сейчас проверить это на GRUB2, но подозреваю что он тоже так умеет, а значит сам скрипт, которым будет выполняться составление "желаемой формы" меню GRUB2, резко упрощается...
Типа "Я определил что это Windows, но хрен знает какая, напишу какую-нибудь ересь", так что-ли отрабатывает скрипт 30_os-prober?
По этому поводу отдельно: а как Вы себе представляете данное "определение"? Есть вариант, к примеру, залезть в системный реестр Windows и вычитать оттуда значение ключика. Для этого надо уметь читать реестр (тот же chntpw, который в штатную поставку не входит). И если положение ключика сместится - что тогда делать скрипту, или если MS с очередным обновлением сам реестр до такой степени модернизируют, что читая его, его ломаешь тут же? Можно попробовать вытянуть информацию из пользовательского соглашения (license.rtf, для прочтения коего нужен хотя бы cat2doc). Однако здесь ещё бОльшее поле вариций, - однозначно научить скрипт трактовать эти соглашения от разных версий Windows будет нельзя. Можно попробовать поискать некие ключевые папки, специфичные для каждой из версий Windows - но это тоже не то. Тут нет универсального решения - поэтому чтобы не городить огород, сделали определение через имя загрузчика (как он сам себя называет), насколько я понимаю. Вот у Вас там ахинея и написана. Только это не отсебятина скрипта - это та ахинея, которую сотрудники MS в данном месте прописали. Скрипт не выдумывает - он просто читает.