core: 兼容 alpine extlinux

This commit is contained in:
bin456789 2024-09-09 22:56:13 +08:00
parent 1b0667a271
commit 925f148fc7
No known key found for this signature in database
GPG Key ID: EE301B386DE6C11B
2 changed files with 198 additions and 101 deletions

View File

@ -141,8 +141,12 @@ is_use_dd() {
[ "$distro" = dd ] [ "$distro" = dd ]
} }
is_boot_in_separate_partition() {
mount | grep -q ' on /boot type '
}
is_os_in_btrfs() { is_os_in_btrfs() {
mount | grep -qw 'on / type btrfs' mount | grep -q ' on / type btrfs '
} }
is_os_in_subvol() { is_os_in_subvol() {
@ -1742,13 +1746,27 @@ is_secure_boot_enabled() {
fi fi
} }
is_use_grub() { is_need_grub_extlinux() {
! { is_netboot_xyz && is_efi; } ! { is_netboot_xyz && is_efi; }
} }
# 只有 linux bios 是用本机的 grub # 只有 linux bios 是用本机的 grub/extlinux
is_use_local_grub_extlinux() {
is_need_grub_extlinux && ! is_in_windows && ! is_efi
}
is_use_local_grub() { is_use_local_grub() {
is_use_grub && ! is_in_windows && ! is_efi is_use_local_grub_extlinux && is_mbr_using_grub
}
is_use_local_extlinux() {
is_use_local_grub_extlinux && ! is_mbr_using_grub
}
is_mbr_using_grub() {
find_main_disk
# 各发行版不一定自带 strings hexdump xxd od 命令
head -c 440 /dev/$xda | grep --text -iq 'GRUB'
} }
to_upper() { to_upper() {
@ -2262,6 +2280,29 @@ install_grub_win() {
fi fi
} }
find_grub_extlinux_cfg() {
dir=$1
filename=$2
keyword=$3
# 当 ln -s /boot/grub /boot/grub2 时
# find /boot/ 会自动忽略 /boot/grub2 里面的文件
cfgs=$(
# 只要 $dir 存在
# 无论是否找到结果,返回值都是 0
find $dir \
-type f -name $filename \
-exec grep -E -l "$keyword" {} \;
)
count="$(wc -l <<<"$cfgs")"
if [ "$count" -eq 1 ]; then
echo "$cfgs"
else
error_and_exit "Find $count $filename."
fi
}
# 转换 finalos_a=1 为 finalos.a=1 ,排除 finalos_mirrorlist # 转换 finalos_a=1 为 finalos.a=1 ,排除 finalos_mirrorlist
build_finalos_cmdline() { build_finalos_cmdline() {
if vars=$(compgen -v finalos_); then if vars=$(compgen -v finalos_); then
@ -3239,7 +3280,7 @@ if [ "$nextos_distro" = alpine ] || is_distro_like_debian "$nextos_distro"; then
fi fi
# 将内核/netboot.xyz.lkrn 放到正确的位置 # 将内核/netboot.xyz.lkrn 放到正确的位置
if false && is_use_grub; then if false && is_need_grub_extlinux; then
if is_in_windows; then if is_in_windows; then
cp -f /reinstall-vmlinuz /cygdrive/$c/ cp -f /reinstall-vmlinuz /cygdrive/$c/
is_have_initrd && cp -f /reinstall-initrd /cygdrive/$c/ is_have_initrd && cp -f /reinstall-initrd /cygdrive/$c/
@ -3251,8 +3292,8 @@ if false && is_use_grub; then
fi fi
fi fi
# grub # grub / extlinux
if is_use_grub; then if is_need_grub_extlinux; then
# win 使用外部 grub # win 使用外部 grub
if is_in_windows; then if is_in_windows; then
install_grub_win install_grub_win
@ -3265,9 +3306,7 @@ if is_use_grub; then
fi fi
fi fi
info 'create grub config' # 寻找 grub.cfg / extlinux.conf
# 寻找 grub.cfg
if is_in_windows; then if is_in_windows; then
if is_efi; then if is_efi; then
grub_cfg=/cygdrive/$c/grub.cfg grub_cfg=/cygdrive/$c/grub.cfg
@ -3282,28 +3321,25 @@ if is_use_grub; then
efi_reinstall_dir=$(find $(get_maybe_efi_dirs_in_linux) -type d -name "reinstall" | head -1) efi_reinstall_dir=$(find $(get_maybe_efi_dirs_in_linux) -type d -name "reinstall" | head -1)
grub_cfg=$efi_reinstall_dir/grub.cfg grub_cfg=$efi_reinstall_dir/grub.cfg
else else
if is_have_cmd update-grub; then if is_mbr_using_grub; then
# alpine debian ubuntu if is_have_cmd update-grub; then
grub_cfg=$(grep -o '[^ ]*grub.cfg' "$(get_cmd_path update-grub)" | head -1) # alpine debian ubuntu
else grub_cfg=$(grep -o '[^ ]*grub.cfg' "$(get_cmd_path update-grub)" | head -1)
# 找出主配置文件含有menuentry|blscfg else
# 现在 efi 用下载的 grub因此不需要查找 efi 目录 # 找出主配置文件含有menuentry|blscfg
grub_cfg=$( # 现在 efi 用下载的 grub因此不需要查找 efi 目录
find /boot/grub* \ grub_cfg=$(find_grub_extlinux_cfg '/boot/grub*' grub.cfg 'menuentry|blscfg')
-type f -name grub.cfg \
-exec grep -E -l 'menuentry|blscfg' {} \;
)
if [ "$(wc -l <<<"$grub_cfg")" -gt 1 ]; then
error_and_exit 'find multi grub.cfg files.'
fi fi
else
# extlinux
extlinux_cfg=$(find_grub_extlinux_cfg /boot extlinux.conf LINUX)
fi fi
fi fi
fi fi
# 判断用 linux 还是 linuxefi主要是红帽系 # 判断用 linux 还是 linuxefi主要是红帽系
# 现在 efi 用下载的 grub因此不需要判断 linux 或 linuxefi # 现在 efi 用下载的 grub因此不需要判断 linux 或 linuxefi
if false && is_use_local_grub; then if false && is_use_local_grub_extlinux; then
# 在x86 efi机器上不同版本的 grub 可能用 linux 或 linuxefi 加载内核 # 在x86 efi机器上不同版本的 grub 可能用 linux 或 linuxefi 加载内核
# 通过检测原有的条目有没有 linuxefi 字样就知道当前 grub 用哪一种 # 通过检测原有的条目有没有 linuxefi 字样就知道当前 grub 用哪一种
# 也可以检测 /etc/grub.d/10_linux # 也可以检测 /etc/grub.d/10_linux
@ -3343,7 +3379,14 @@ if is_use_grub; then
fi fi
fi fi
# 选择用 custom.cfg (linux-bios) 还是 grub.cfg (win/linux-efi) # 重新生成 extlinux.conf
if is_use_local_extlinux; then
if is_have_cmd update-extlinux; then
update-extlinux
fi
fi
# 选择用 custom.cfg (linux-bios) 还是 grub.cfg (linux-efi / win)
if is_use_local_grub; then if is_use_local_grub; then
target_cfg=$(dirname $grub_cfg)/custom.cfg target_cfg=$(dirname $grub_cfg)/custom.cfg
else else
@ -3355,16 +3398,22 @@ if is_use_grub; then
# dir=/cygwin/ # dir=/cygwin/
dir=$(cygpath -m / | cut -d: -f2-)/ dir=$(cygpath -m / | cut -d: -f2-)/
else else
# 获取当前系统根目录在 btrfs 中的绝对路径 # extlinux + 单独的 boot 分区
if is_os_in_btrfs; then # 把内核文件放在 extlinux.conf 所在的目录
# btrfs subvolume show / if is_use_local_extlinux && is_boot_in_separate_partition; then
# 输出可能是 / 或 root 或 @/.snapshots/1/snapshot dir=
dir=$(btrfs subvolume show / | head -1)
if ! [ "$dir" = / ]; then
dir="/$dir/"
fi
else else
dir=/ # 获取当前系统根目录在 btrfs 中的绝对路径
if is_os_in_btrfs; then
# btrfs subvolume show /
# 输出可能是 / 或 root 或 @/.snapshots/1/snapshot
dir=$(btrfs subvolume show / | head -1)
if ! [ "$dir" = / ]; then
dir="/$dir/"
fi
else
dir=/
fi
fi fi
fi fi
@ -3372,62 +3421,105 @@ if is_use_grub; then
initrd=${dir}reinstall-initrd initrd=${dir}reinstall-initrd
firmware=${dir}reinstall-firmware firmware=${dir}reinstall-firmware
# 生成 linux initrd 命令 # 设置 linux initrd 命令
if is_netboot_xyz; then if is_use_local_extlinux; then
linux_cmd="linux16 $vmlinuz" linux_cmd=LINUX
initrd_cmd=INITRD
else else
find_main_disk if is_netboot_xyz; then
build_cmdline linux_cmd=linux16
linux_cmd="linux$efi $vmlinuz $cmdline" initrd_cmd=initrd16
initrd_cmd="initrd$efi $initrd" else
if is_use_firmware; then linux_cmd="linux$efi"
initrd_cmd+=" $firmware" initrd_cmd="initrd$efi"
fi fi
fi fi
# cloudcone 从光驱的 grub 启动,再加载硬盘的 grub.cfg # 设置 cmdlind initrds
# menuentry "Grub 2" --id grub2 { if ! is_netboot_xyz; then
# set root=(hd0,msdos1) find_main_disk
# configfile /boot/grub2/grub.cfg build_cmdline
# }
# 加载后 $prefix 依然是光驱的 (hd96)/boot/grub initrds="$initrd"
# 导致找不到 $prefix 目录的 grubenv因此读取不到 next_entry if is_use_firmware; then
# 以下方法为 cloudcone 重新加载 grubenv initrds+=" $firmware"
# 需查找 2*2 个文件夹
# 分区:系统 / boot
# 文件夹grub / grub2
# shellcheck disable=SC2121,SC2154
# cloudcone debian 能用但 ubuntu 模板用不了
# ubuntu 模板甚至没显示 reinstall menuentry
load_grubenv_if_not_loaded() {
if ! [ -s $prefix/grubenv ]; then
for dir in /boot/grub /boot/grub2 /grub /grub2; do
set grubenv="($root)$dir/grubenv"
if [ -s $grubenv ]; then
load_env --file $grubenv
if [ "${next_entry}" ]; then
set default="${next_entry}"
set next_entry=
save_env --file $grubenv next_entry
else
set default="0"
fi
return
fi
done
fi fi
} fi
# 生成 grub 配置 if is_use_local_extlinux; then
# 实测 centos 7 lvm 要手动加载 lvm 模块 info extlinux
echo $target_cfg echo $extlinux_cfg
extlinux_dir="$(dirname $extlinux_cfg)"
get_function_content load_grubenv_if_not_loaded >$target_cfg # 不起作用
# 好像跟 extlinux --once 有冲突
sed -i "/^MENU HIDDEN/d" $extlinux_cfg
sed -i "/^TIMEOUT /d" $extlinux_cfg
# 原系统为 openeuler 云镜像,需要添加 --unrestricted否则要输入密码 del_empty_lines <<EOF | tee -a $extlinux_cfg
del_empty_lines <<EOF | tee -a $target_cfg TIMEOUT 5
LABEL reinstall
MENU LABEL $(get_entry_name)
$linux_cmd $vmlinuz
$([ -n "$initrds" ] && echo "$initrd_cmd $initrds")
$([ -n "$cmdline" ] && echo "APPEND $cmdline")
EOF
# 设置重启引导项
extlinux --once=reinstall $extlinux_dir
# 复制文件到 extlinux 工作目录
if is_boot_in_separate_partition; then
info "copying files to $extlinux_dir"
is_have_initrd && cp -f /reinstall-initrd $extlinux_dir
is_use_firmware && cp -f /reinstall-firmware $extlinux_dir
# 放最后,防止前两条返回非 0 而报错
cp -f /reinstall-vmlinuz $extlinux_dir
fi
else
# cloudcone 从光驱的 grub 启动,再加载硬盘的 grub.cfg
# menuentry "Grub 2" --id grub2 {
# set root=(hd0,msdos1)
# configfile /boot/grub2/grub.cfg
# }
# 加载后 $prefix 依然是光驱的 (hd96)/boot/grub
# 导致找不到 $prefix 目录的 grubenv因此读取不到 next_entry
# 以下方法为 cloudcone 重新加载 grubenv
# 需查找 2*2 个文件夹
# 分区:系统 / boot
# 文件夹grub / grub2
# shellcheck disable=SC2121,SC2154
# cloudcone debian 能用但 ubuntu 模板用不了
# ubuntu 模板甚至没显示 reinstall menuentry
load_grubenv_if_not_loaded() {
if ! [ -s $prefix/grubenv ]; then
for dir in /boot/grub /boot/grub2 /grub /grub2; do
set grubenv="($root)$dir/grubenv"
if [ -s $grubenv ]; then
load_env --file $grubenv
if [ "${next_entry}" ]; then
set default="${next_entry}"
set next_entry=
save_env --file $grubenv next_entry
else
set default="0"
fi
return
fi
done
fi
}
# 生成 grub 配置
# 实测 centos 7 lvm 要手动加载 lvm 模块
info grub
echo $target_cfg
get_function_content load_grubenv_if_not_loaded >$target_cfg
# 原系统为 openeuler 云镜像,需要添加 --unrestricted否则要输入密码
del_empty_lines <<EOF | tee -a $target_cfg
set timeout_style=menu set timeout_style=menu
set timeout=5 set timeout=5
menuentry "$(get_entry_name)" --unrestricted { menuentry "$(get_entry_name)" --unrestricted {
@ -3435,14 +3527,15 @@ menuentry "$(get_entry_name)" --unrestricted {
$(is_os_in_btrfs && echo 'set btrfs_relative_path=n') $(is_os_in_btrfs && echo 'set btrfs_relative_path=n')
insmod all_video insmod all_video
search --no-floppy --file --set=root $vmlinuz search --no-floppy --file --set=root $vmlinuz
$linux_cmd $linux_cmd $vmlinuz $cmdline
$initrd_cmd $([ -n "$initrds" ] && echo "$initrd_cmd $initrds")
} }
EOF EOF
# 设置重启引导项 # 设置重启引导项
if is_use_local_grub; then if is_use_local_grub; then
$grub-reboot "$(get_entry_name)" $grub-reboot "$(get_entry_name)"
fi
fi fi
fi fi

View File

@ -1861,6 +1861,10 @@ create_part() {
mkfs.ext4 -E nodiscard -F -L installer /dev/$xda*2 #2 installer mkfs.ext4 -E nodiscard -F -L installer /dev/$xda*2 #2 installer
fi fi
elif [ "$distro" = alpine ] || [ "$distro" = arch ] || [ "$distro" = gentoo ] || [ "$distro" = nixos ]; then elif [ "$distro" = alpine ] || [ "$distro" = arch ] || [ "$distro" = gentoo ] || [ "$distro" = nixos ]; then
# alpine 本身关闭了 64bit ext4
# https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/3.18.1/setup-disk.in?ref_type=tags#L908
# 而且 alpine 的 extlinux 不兼容 64bit ext4
[ "$distro" = alpine ] && ext4_opts="-O ^64bit" || ext4_opts=
if is_efi; then if is_efi; then
# efi # efi
parted /dev/$xda -s -- \ parted /dev/$xda -s -- \
@ -1870,8 +1874,8 @@ create_part() {
set 1 boot on set 1 boot on
update_part update_part
mkfs.fat /dev/$xda*1 #1 efi mkfs.fat /dev/$xda*1 #1 efi
mkfs.ext4 -E nodiscard -F /dev/$xda*2 #2 os mkfs.ext4 -E nodiscard -F $ext4_opts /dev/$xda*2 #2 os
elif is_xda_gt_2t; then elif is_xda_gt_2t; then
# bios > 2t # bios > 2t
parted /dev/$xda -s -- \ parted /dev/$xda -s -- \
@ -1881,8 +1885,8 @@ create_part() {
set 1 bios_grub on set 1 bios_grub on
update_part update_part
echo #1 bios_boot echo #1 bios_boot
mkfs.ext4 -E nodiscard -F /dev/$xda*2 #2 os mkfs.ext4 -E nodiscard -F $ext4_opts /dev/$xda*2 #2 os
else else
# bios # bios
parted /dev/$xda -s -- \ parted /dev/$xda -s -- \
@ -1891,7 +1895,7 @@ create_part() {
set 1 boot on set 1 boot on
update_part update_part
mkfs.ext4 -E nodiscard -F /dev/$xda*1 #1 os mkfs.ext4 -E nodiscard -F $ext4_opts /dev/$xda*1 #1 os
fi fi
else else
# 安装红帽系或ubuntu # 安装红帽系或ubuntu
@ -1913,7 +1917,7 @@ create_part() {
# centos 7 无法加载alpine格式化的ext4 # centos 7 无法加载alpine格式化的ext4
# 要关闭这个属性 # 要关闭这个属性
ext4_options="-O ^metadata_csum" ext4_opts="-O ^metadata_csum"
apk add dosfstools apk add dosfstools
if is_efi; then if is_efi; then
@ -1926,9 +1930,9 @@ create_part() {
set 1 boot on set 1 boot on
update_part update_part
mkfs.fat -n efi /dev/$xda*1 #1 efi mkfs.fat -n efi /dev/$xda*1 #1 efi
mkfs.ext4 -E nodiscard -F -L os /dev/$xda*2 #2 os mkfs.ext4 -E nodiscard -F -L os /dev/$xda*2 #2 os
mkfs.ext4 -E nodiscard -F -L installer $ext4_options /dev/$xda*3 #2 installer mkfs.ext4 -E nodiscard -F -L installer $ext4_opts /dev/$xda*3 #2 installer
elif is_xda_gt_2t; then elif is_xda_gt_2t; then
# bios > 2t # bios > 2t
parted /dev/$xda -s -- \ parted /dev/$xda -s -- \
@ -1939,9 +1943,9 @@ create_part() {
set 1 bios_grub on set 1 bios_grub on
update_part update_part
echo #1 bios_boot echo #1 bios_boot
mkfs.ext4 -E nodiscard -F -L os /dev/$xda*2 #2 os mkfs.ext4 -E nodiscard -F -L os /dev/$xda*2 #2 os
mkfs.ext4 -E nodiscard -F -L installer $ext4_options /dev/$xda*3 #3 installer mkfs.ext4 -E nodiscard -F -L installer $ext4_opts /dev/$xda*3 #3 installer
else else
# bios # bios
parted /dev/$xda -s -- \ parted /dev/$xda -s -- \
@ -1951,8 +1955,8 @@ create_part() {
set 1 boot on set 1 boot on
update_part update_part
mkfs.ext4 -E nodiscard -F -L os /dev/$xda*1 #1 os mkfs.ext4 -E nodiscard -F -L os /dev/$xda*1 #1 os
mkfs.ext4 -E nodiscard -F -L installer $ext4_options /dev/$xda*2 #2 installer mkfs.ext4 -E nodiscard -F -L installer $ext4_opts /dev/$xda*2 #2 installer
fi fi
update_part update_part
fi fi