From db1b2c92cadb36a06de60f4863e7b499af639bd7 Mon Sep 17 00:00:00 2001 From: bin456789 Date: Thu, 1 Feb 2024 00:59:34 +0800 Subject: [PATCH] =?UTF-8?q?core:=20=E8=AE=B0=E5=BD=95=E4=B8=BB=E7=A1=AC?= =?UTF-8?q?=E7=9B=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- redhat.cfg | 34 +++++++------ reinstall.sh | 108 ++++++++++++++++++++++++++++++++++++---- trans.sh | 80 ++++++++++++++++++++++++----- ubuntu-storage-early.sh | 25 ++++++---- ubuntu.yaml | 1 + 5 files changed, 201 insertions(+), 47 deletions(-) diff --git a/redhat.cfg b/redhat.cfg index 8aba238..fda08cf 100644 --- a/redhat.cfg +++ b/redhat.cfg @@ -34,29 +34,35 @@ selinux --disabled ############################################## %pre -get_xda() { - # 排除只读盘,vda 放前面 - # 有的机器有sda和vda,vda是主硬盘,另一个盘是只读 - for _xda in vda xda sda hda xvda nvme0n1; do - if [ -e "/sys/class/block/$_xda/ro" ] && - [ "$(cat /sys/class/block/$_xda/ro)" = 0 ]; then - echo $_xda - return - fi - done - return 1 -} - distro=$(awk -F: '{ print $3 }' $include diff --git a/reinstall.sh b/reinstall.sh index 564e272..16dbfe6 100644 --- a/reinstall.sh +++ b/reinstall.sh @@ -683,7 +683,25 @@ install_pkg() { cmd_to_pkg() { unset USE case $cmd in - lsmem | lsblk | findmnt) pkg="util-linux" ;; + lsblk | findmnt) + case "$pkg_mgr" in + apk) pkg="$cmd" ;; + *) pkg="util-linux" ;; + esac + ;; + lsmem) + case "$pkg_mgr" in + apk) pkg="util-linux-misc" ;; + *) pkg="util-linux" ;; + esac + ;; + fdisk) + case "$pkg_mgr" in + apt) pkg="fdisk" ;; + apk) pkg="util-linux-misc" ;; + *) pkg="util-linux" ;; + esac + ;; unsquashfs) case "$pkg_mgr" in zypper) pkg="squashfs" ;; @@ -704,6 +722,7 @@ install_pkg() { } install_pkg_real() { + echo "Installing package '$pkg' for command '$cmd'..." case $pkg_mgr in dnf) dnf install -y --setopt=install_weak_deps=False $pkg ;; yum) yum install -y $pkg ;; @@ -721,18 +740,30 @@ install_pkg() { esac } - is_need_rebuild() { + is_need_reinstall() { cmd=$1 + # gentoo 默认编译的 unsquashfs 不支持 xz - if [ "$cmd" = unsquashfs ] && is_have_cmd emerge && ! unsquashfs |& grep -w xz; then + if [ "$cmd" = unsquashfs ] && is_have_cmd emerge && ! $cmd |& grep -wq xz; then echo "unsquashfs not supported xz. rebuilding." return 0 fi + + # busybox fdisk 无法显示 mbr 分区表的 id + if [ "$cmd" = fdisk ] && is_have_cmd apk && $cmd |& grep -wq BusyBox; then + return 0 + fi + + # busybox grep 无法 grep -oP + if [ "$cmd" = grep ] && is_have_cmd apk && $cmd |& grep -wq BusyBox; then + return 0 + fi + return 1 } for cmd in "$@"; do - if ! is_have_cmd $cmd || is_need_rebuild $cmd; then + if ! is_have_cmd $cmd || is_need_reinstall $cmd; then if ! find_pkg_mgr; then error_and_exit "Can't find compatible package manager. Please manually install $cmd." fi @@ -837,6 +868,64 @@ del_cr() { sed 's/\r//g' } +# 记录主硬盘 +find_main_disk() { + if is_in_windows; then + # TODO: + # 已测试 vista + # 测试 软raid + # 测试 动态磁盘 + + # diskpart 命令结果 + # 磁盘 ID: E5FDE61C + # 磁盘 ID: {92CF6564-9B2E-4348-A3BD-D84E3507EBD7} + disk_index=$(wmic logicaldisk where "DeviceID='$c:'" assoc:value /resultclass:Win32_DiskPartition | + grep 'DiskIndex=' | cut -d= -f2 | del_cr) + main_disk=$(printf "%s\n%s" "select disk $disk_index" "uniqueid disk" | diskpart | + tail -1 | awk '{print $NF}' | sed 's,[{}],,g' | del_cr) + else + # centos7下测试 lsblk --inverse $mapper | grep -w disk grub2-probe -t disk / + # 跨硬盘btrfs 只显示第一个硬盘 显示两个硬盘 + # 跨硬盘lvm 显示两个硬盘 显示/dev/mapper/centos-root + # 跨硬盘软raid 显示两个硬盘 显示/dev/md127 + + # 改成先检测 /boot/efi /efi /boot 分区? + + install_pkg lsblk + # lvm 显示的是 /dev/mapper/xxx-yyy,再用第二条命令得到sda + mapper=$(mount | awk '$3=="/" {print $1}') + xda=$(lsblk -rn --inverse $mapper | grep -w disk | awk '{print $1}' | sort -u) + + # 检测主硬盘是否横跨多个磁盘 + os_across_disks_count=$(wc -l <<<"$xda") + if [ $os_across_disks_count -eq 1 ]; then + info "Main disk: $xda" + else + error_and_exit "OS across $os_across_disks_count disk: $xda" + fi + + # 可以用 dd 找出 guid? + + # centos7 sfdisk 不显示 Disk identifier + # 因此用 fdisk + + # Disk identifier: 0x36778223 # gnu fdisk + mbr + # Disk identifier: D6B17C1A-FA1E-40A1-BDCB-0278A3ED9CFC # gnu fdisk + gpt + # Disk identifier (GUID): d6b17c1a-fa1e-40a1-bdcb-0278a3ed9cfc # busybox fdisk + gpt + # 不显示 Disk identifier # busybox fdisk + mbr + + # 获取 xda 的 id + install_pkg fdisk + main_disk=$(fdisk -l /dev/$xda | grep 'Disk identifier' | awk '{print $NF}' | sed 's/0x//') + fi + + # 检查 id 格式是否正确 + if ! grep -Eix '[0-9a-f]{8}' <<<"$main_disk" && + ! grep -Eix '[0-9a-f-]{36}' <<<"$main_disk"; then + error_and_exit "Disk ID is invalid: $main_disk" + fi +} + # TODO: 多网卡 单网卡多IP collect_netconf() { if is_in_windows; then @@ -980,7 +1069,7 @@ get_maybe_efi_dirs_in_linux() { get_disk_by_part() { dev_part=$1 - install_pkg lsblk + install_pkg lsblk >&2 lsblk -rn --inverse "$dev_part" | grep -w disk | awk '{print $1}' } @@ -1183,7 +1272,7 @@ build_finalos_cmdline() { } build_extra_cmdline() { - for key in confhome hold cloud_image kernel deb_hostname; do + for key in confhome hold cloud_image kernel deb_hostname main_disk; do value=${!key} if [ -n "$value" ]; then extra_cmdline+=" extra.$key='$value'" @@ -1462,11 +1551,7 @@ if is_in_windows; then fi # 必备组件 -install_pkg curl -# alpine 自带的 grep 是 busybox 里面的, 要下载完整版grep -if is_in_alpine; then - apk add grep -fi +install_pkg curl grep # 检查内存 if ! { [ "$distro" = dd ] || [ "$distro" = windows ] || [ "$distro" = netboot.xyz ]; }; then @@ -1689,6 +1774,7 @@ if is_use_grub; then if is_netboot_xyz; then linux_cmd="linux16 /reinstall-vmlinuz" else + find_main_disk build_cmdline linux_cmd="linux$efi /reinstall-vmlinuz $cmdline" initrd_cmd="initrd$efi /reinstall-initrd" diff --git a/trans.sh b/trans.sh index 1e94aaa..fbb89dc 100644 --- a/trans.sh +++ b/trans.sh @@ -210,18 +210,50 @@ get_ttys() { wget $confhome/ttys.sh -O- | sh -s $prefix } -get_xda() { - # 排除只读盘,vda 放前面 - # 有的机器有sda和vda,vda是主硬盘,另一个盘是只读 - # TODO: 找出容量最大的? - for _xda in vda xda sda hda xvda nvme0n1; do - if [ -e "/sys/class/block/$_xda/ro" ] && - [ "$(cat /sys/class/block/$_xda/ro)" = 0 ]; then - echo $_xda - return +find_xda() { + # 防止 $main_disk 为空 + if [ -z "$main_disk" ]; then + error_and_exit "cmdline main_disk is empty." + fi + + # busybox fdisk 不显示 mbr 分区表 id + # fdisk 在 util-linux-misc 里面,占用大 + # sfdisk 占用小 + if is_have_cmd sfdisk; then + need_del_sfdisk=false + else + apk add sfdisk + need_del_sfdisk=true + fi + + for disk in $(get_all_disks); do + if sfdisk --disk-id "/dev/$disk" | sed 's/0x//' | grep -ix "$main_disk"; then + xda=$disk + break + fi + done + + if [ -z "$xda" ]; then + error_and_exit "Could not find xda: $main_disk" + fi + + if $need_del_sfdisk; then + apk del sfdisk + fi +} + +get_all_disks() { + # busybox blkid 不接受任何参数 + # lsblk 要另外安装 + disks=$(blkid | cut -d: -f1 | cut -d/ -f3 | sed -E 's/p?[0-9]+$//' | sort -u) + + # blkid 会显示 sr0,经过上面的命令输出为 sr + # 因此要检测是否有效 + for disk in $disks; do + if [ -b "/dev/$disk" ]; then + echo "$disk" fi done - return 1 } setup_tty_and_log() { @@ -2219,6 +2251,21 @@ download_netboot_xyz_efi() { fi } +refind_main_disk() { + if is_have_cmd sfdisk; then + need_del_sfdisk=false + else + apk add sfdisk + need_del_sfdisk=true + fi + + main_disk="$(sfdisk --disk-id "/dev/$xda" | sed 's/0x//')" + + if $need_del_sfdisk; then + apk del sfdisk + fi +} + install_redhat_ubuntu() { # 安装 grub2 if is_efi; then @@ -2232,8 +2279,15 @@ install_redhat_ubuntu() { fi # 重新整理 extra,因为grub会处理掉引号,要重新添加引号 + extra_cmdline='' for var in $(grep -o '\bextra\.[^ ]*' /proc/cmdline | xargs); do - extra_cmdline="$extra_cmdline $(echo $var | sed -E "s/(extra\.[^=]*)=(.*)/\1='\2'/")" + if [[ "$var" = "extra.main_disk="* ]]; then + # 重新记录主硬盘 + refind_main_disk + extra_cmdline="$extra_cmdline extra.main_disk=$main_disk" + else + extra_cmdline="$extra_cmdline $(echo $var | sed -E "s/(extra\.[^=]*)=(.*)/\1='\2'/")" + fi done # 安装红帽系时,只有最后一个有安装界面显示 @@ -2315,8 +2369,8 @@ cat /proc/cmdline clear_previous add_community_repo -# 找到主硬盘 -xda=$(get_xda) +# 需要在重新分区之前,找到主硬盘 +find_xda if [ "$distro" != "alpine" ]; then setup_nginx_if_enough_ram diff --git a/ubuntu-storage-early.sh b/ubuntu-storage-early.sh index b71eb75..95ff165 100644 --- a/ubuntu-storage-early.sh +++ b/ubuntu-storage-early.sh @@ -1,16 +1,22 @@ #!/bin/bash +get_all_disks() { + lsblk -rn --nodeps -o NAME,TYPE | grep 'disk$' | awk '{print $1}' +} + get_xda() { - # 排除只读盘,vda 放前面 - # 有的机器有sda和vda,vda是主硬盘,另一个盘是只读 - for _xda in vda xda sda hda xvda nvme0n1; do - if [ -e "/sys/class/block/$_xda/ro" ] && - [ "$(cat /sys/class/block/$_xda/ro)" = 0 ]; then - echo $_xda - return + # 防止 $main_disk 为空 + if [ -z "$main_disk" ]; then + return + fi + + for disk in $(get_all_disks); do + # shellcheck disable=SC2154 + if fdisk -l "/dev/$disk" | grep -iq "$main_disk"; then + echo "$disk" + break fi done - return 1 } sed -i -E '/^\.{3}$/d' /autoinstall.yaml @@ -22,7 +28,8 @@ cat <>/autoinstall.yaml size: 0 EOF -xda=$(get_xda) +xda="$(get_xda)" + # 是用 size 寻找分区,number 没什么用 # https://curtin.readthedocs.io/en/latest/topics/storage.html size_os=$(lsblk -bn -o SIZE /dev/disk/by-label/os) diff --git a/ubuntu.yaml b/ubuntu.yaml index 8240181..e9e306d 100644 --- a/ubuntu.yaml +++ b/ubuntu.yaml @@ -27,6 +27,7 @@ autoinstall: done # 生成分区信息 + export main_disk curl -L $confhome/ubuntu-storage-early.sh | bash -s # 内核风味