diff --git a/README.en.md b/README.en.md index 5e2d7b8..0f00d2e 100644 --- a/README.en.md +++ b/README.en.md @@ -29,8 +29,11 @@ Reinstall server with one-click [中文](README.md) | Kali | Rolling | 256 MB | 1 ~ 1.5 GB ^ | | Ubuntu | 20.04, 22.04, 24.04 | 512 MB \* | 2 GB | | CentOS | 9 | 512 MB \* | 5 GB | +| Anolis OS | 7, 8 | 512 MB \* | 5 GB | | RedHat   Alma   Rocky   Oracle | 8, 9 | 512 MB \* | 5 GB | +| OpenCloudOS | 8, 9 | 512 MB \* | 5 GB | | Fedora | 39, 40 | 512 MB \* | 5 GB | +| openEuler | 20.03, 22.03, 24.03 | 512 MB \* | 5 GB | | openSUSE | 15.5, 15.6, Tumbleweed (Rolling) | 512 MB \* | 5 GB | | Arch | Rolling | 512 MB | 5 GB | | Gentoo | Rolling | 512 MB | 5 GB | @@ -140,16 +143,19 @@ certutil -urlcache -f -split https://mirror.ghproxy.com/https://raw.githubuserco > See ```bash -bash reinstall.sh centos 9 - alma 8|9 - rocky 8|9 - oracle 8|9 - redhat 8|9 --img 'https://xxx.qcow2' - fedora 39|40 - debian 11|12 - ubuntu 20.04|22.04|24.04 - alpine 3.17|3.18|3.19|3.20 - opensuse 15.5|15.6|tumbleweed +bash reinstall.sh centos 9 + anolis 7|8 + alma 8|9 + rocky 8|9 + oracle 8|9 + redhat 8|9 --img='http://xxx.qcow2' + opencloudos 8|9 + fedora 39|40 + debian 11|12 + openeuler 20.03|22.03|24.03 + ubuntu 20.04|22.04|24.04 + alpine 3.17|3.18|3.19|3.20 + opensuse 15.5|15.6|tumbleweed kali arch gentoo diff --git a/README.md b/README.md index f5571fb..706749d 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,11 @@ | Kali | 滚动 | 256 MB | 1 ~ 1.5 GB ^ | | Ubuntu | 20.04, 22.04, 24.04 | 512 MB \* | 2 GB | | CentOS | 9 | 512 MB \* | 5 GB | +| Anolis OS | 7, 8 | 512 MB \* | 5 GB | | RedHat   Alma   Rocky   Oracle | 8, 9 | 512 MB \* | 5 GB | +| OpenCloudOS | 8, 9 | 512 MB \* | 5 GB | | Fedora | 39, 40 | 512 MB \* | 5 GB | +| openEuler | 20.03, 22.03, 24.03 | 512 MB \* | 5 GB | | openSUSE | 15.5, 15.6, Tumbleweed (滚动) | 512 MB \* | 5 GB | | Arch | 滚动 | 512 MB | 5 GB | | Gentoo | 滚动 | 512 MB | 5 GB | @@ -140,16 +143,19 @@ certutil -urlcache -f -split https://mirror.ghproxy.com/https://raw.githubuserco > ```bash -bash reinstall.sh centos 9 - alma 8|9 - rocky 8|9 - oracle 8|9 - redhat 8|9 --img 'https://xxx.qcow2' - fedora 39|40 - debian 11|12 - ubuntu 20.04|22.04|24.04 - alpine 3.17|3.18|3.19|3.20 - opensuse 15.5|15.6|tumbleweed +bash reinstall.sh centos 9 + anolis 7|8 + alma 8|9 + rocky 8|9 + oracle 8|9 + redhat 8|9 --img='http://xxx.qcow2' + opencloudos 8|9 + fedora 39|40 + debian 11|12 + openeuler 20.03|22.03|24.03 + ubuntu 20.04|22.04|24.04 + alpine 3.17|3.18|3.19|3.20 + opensuse 15.5|15.6|tumbleweed kali arch gentoo diff --git a/reinstall.sh b/reinstall.sh index 9d9b95c..82fe1d3 100644 --- a/reinstall.sh +++ b/reinstall.sh @@ -30,22 +30,25 @@ usage_and_exit() { reinstall____='./reinstall.sh' fi cat </dev/null } +is_have_cmd_on_disk() { + os_dir=$1 + cmd=$2 + + for bin_dir in /bin /sbin /usr/bin /usr/sbin; do + if [ -f "$os_dir$bin_dir/$cmd" ]; then + return + fi + done + return 1 +} + download() { url=$1 path=$2 @@ -320,7 +332,7 @@ EOF } umount_all() { - dirs="/os /iso /wim /installer /nbd /nbd-boot /nbd-efi /root" + dirs="/mnt /os /iso /wim /installer /nbd /nbd-boot /nbd-efi /root" regex=$(echo "$dirs" | sed 's, ,|,g') if mounts=$(mount | grep -Ew "$regex" | awk '{print $3}' | tac); then for mount in $mounts; do @@ -1356,6 +1368,7 @@ create_part() { # 这几个系统不使用dd,而是复制文件 if [ "$distro" = centos ] || [ "$distro" = alma ] || [ "$distro" = rocky ] || [ "$distro" = oracle ] || [ "$distro" = redhat ] || + [ "$distro" = anolis ] || [ "$distro" = opencloudos ] || [ "$distro" = openeuler ] || [ "$distro" = ubuntu ]; then fs="$(get_os_fs)" if is_efi; then @@ -1579,8 +1592,20 @@ create_cloud_init_network_config() { elif is_staticv6; then get_netconf_to ipv6_addr get_netconf_to ipv6_gateway + # el7 不认识 static6,但可改成 static,作用相同 + # >=20.1 修复 + # https://github.com/canonical/cloud-init/commit/dacdd30080bd8183d1f1c1dc9dbcbc8448301529 + # anolis 7: cloud-init 19.1 + # openeuler 20.03: cloud-init 19.4 + # shellcheck disable=SC2154 + if { [ "$distro" = anolis ] && [ "$releasever" = 7 ]; } || + { [ "$distro" = openeuler ] && [ "$releasever" = 20.03 ]; }; then + type_ipv6_static=static + else + type_ipv6_static=static6 + fi yq -i ".network.config[$config_id].subnets[$subnet_id] = { - \"type\": \"static6\", + \"type\": \"$type_ipv6_static\", \"address\": \"$ipv6_addr\", \"gateway\": \"$ipv6_gateway\" } " $ci_file @@ -2041,18 +2066,38 @@ allow_root_password_login() { disable_selinux_kdump() { os_dir=$1 - releasever=$(awk -F: '{ print $5 }' $os_dir/etc/system-release-cpe) # selinux - sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' $os_dir/etc/selinux/config + if [ -f $os_dir/etc/selinux/config ]; then + sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' $os_dir/etc/selinux/config + fi + # https://access.redhat.com/solutions/3176 - if [ "$releasever" -ge 9 ]; then + # shellcheck disable=SC2154 + # openeuler 版本是 24.03 + if [ "$distro" = openeuler ] || [ "$releasever" -ge 9 ]; then chroot $os_dir grubby --update-kernel ALL --args selinux=0 fi # kdump + # grubby 只处理 GRUB_CMDLINE_LINUX,不会处理 GRUB_CMDLINE_LINUX_DEFAULT + # rocky 的 GRUB_CMDLINE_LINUX_DEFAULT 有 crashkernel=auto + + # 新安装的内核依然有 crashkernel,好像是 bug + # https://forums.rockylinux.org/t/how-do-i-remove-crashkernel-from-cmdline/13346 + # 验证过程 + # yum remove --oldinstallonly # 删除旧内核 + # rm -rf /boot/loader/entries/* # 删除启动条目 + # yum reinstall kernel-core # 重新安装新内核 + # cat /boot/loader/entries/* # 依然有 crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M + + sed -i 's/crashkernel=[^ ]*/crashkernel=no/' $os_dir/etc/default/grub chroot $os_dir grubby --update-kernel ALL --args crashkernel=no - chroot $os_dir systemctl disable kdump + # el7 上面那条 grubby 命令不能设置 /etc/default/grub + sed -i 's/crashkernel=[^ "]*/crashkernel=no/' $os_dir/etc/default/grub + if chroot $os_dir systemctl is-enabled kdump; then + chroot $os_dir systemctl disable kdump + fi } download_qcow() { @@ -2060,8 +2105,15 @@ download_qcow() { mkdir -p /installer mount /dev/disk/by-label/installer /installer + qcow_file=/installer/cloud_image.qcow2 - download $img $qcow_file + if [ "$distro" = openeuler ]; then + prog=xz + apk add wget $prog + command wget $img -O- --tries=5 --progress=bar:force | $prog -dc >$qcow_file + else + download "$img" "$qcow_file" + fi } connect_qcow() { @@ -2091,24 +2143,58 @@ disconnect_qcow() { get_os_fs() { case "$distro" in ubuntu) echo ext4 ;; + anolis | openeuler) echo ext4 ;; centos | alma | rocky | oracle | redhat) echo xfs ;; + opencloudos) echo xfs ;; esac } get_ci_installer_part_size() { - case "$distro" in - centos | alma | rocky | oracle | redhat) echo 2GiB ;; - *) echo 1GiB ;; - esac + # 8 + # https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-latest.x86_64.qcow2 600m + # https://download.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base.latest.x86_64.qcow2 1.8g + # https://yum.oracle.com/templates/OracleLinux/OL8/u9/x86_64/OL8U9_x86_64-kvm-b219.qcow2 1g + # https://rhel-8.10-x86_64-kvm.qcow2 1g + + # 9 + # https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-latest.x86_64.qcow2 1.2g + # https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2 600m + # https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 600m + # https://yum.oracle.com/templates/OracleLinux/OL9/u3/x86_64/OL9U3_x86_64-kvm-b220.qcow2 600m + # rhel-9.4-x86_64-kvm.qcow2 900m + + # https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/cloud/nocloud_alpine-3.19.1-x86_64-uefi-cloudinit-r0.qcow2 200m + # https://kali.download/cloud-images/current/kali-linux-2024.1-cloud-genericcloud-amd64.tar.xz 200m + # https://download.opensuse.org/tumbleweed/appliances/openSUSE-Tumbleweed-Minimal-VM.x86_64-Cloud.qcow2 300m + # https://download.opensuse.org/distribution/leap/15.5/appliances/openSUSE-Leap-15.5-Minimal-VM.aarch64-Cloud.qcow2 300m + # https://mirror.fcix.net/fedora/linux/releases/40/Cloud/x86_64/images/Fedora-Cloud-Base-Generic.x86_64-40-1.14.qcow2 400m + # https://geo.mirror.pkgbuild.com/images/latest/Arch-Linux-x86_64-cloudimg.qcow2 500m + # https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2 500m + # https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img 500m + # https://gentoo.osuosl.org/experimental/amd64/openstack/gentoo-openstack-amd64-systemd-latest.qcow2 800m + + # openeuler 20.03 3g + if [ "$distro" = openeuler ]; then + echo 3GiB + else + if get_http_file_size_to size_bytes $img >&2 && [ -n "$size_bytes" ]; then + # 额外 +100M 文件系统保留大小 和 qcow2 写入空间 + size_bytes_mb=$((size_bytes / 1024 / 1024 + 100)) + # 最少 1g ,因为可能要用作临时 swap + echo "$((size_bytes_mb / 1024 + 1))GiB" + else + # 如果没获取到文件大小 + echo 2GiB + fi + fi } chroot_dnf() { - if [ "$distro" = oracle ]; then - enablerepo=ol${releasever}_baseos_latest + if is_have_cmd_on_disk /os/ dnf; then + chroot /os/ dnf -y "$@" else - enablerepo=baseos + chroot /os/ yum -y "$@" fi - chroot /os/ dnf -y --disablerepo=* --enablerepo=$enablerepo --setopt=install_weak_deps=False "$@" } chroot_apt_autoremove() { @@ -2122,7 +2208,7 @@ chroot_apt_autoremove() { install_qcow_by_copy() { mount_nouuid() { - case "$fs" in + case "$(get_os_fs)" in ext4) mount "$@" ;; xfs) mount -o nouuid "$@" ;; esac @@ -2141,21 +2227,43 @@ install_qcow_by_copy() { # centos/rocky/alma/rhel: xfs # oracle x86_64: lvm + xfs # oracle aarch64 cloud: xfs + + is_lvm_image=false if lsblk -f /dev/nbd0p* | grep LVM2_member; then + is_lvm_image=true apk add lvm2 lvscan - lvchange -ay vg_main - os_part=mapper/vg_main-lv_root - boot_part=nbd0p1 - else - # TODO: 改成循环mount找出os+fstab查找剩余分区? - os_part=$(lsblk /dev/nbd0p* --sort SIZE -no NAME,FSTYPE | grep -E 'ext4|xfs' | tail -1 | cut -d' ' -f1) - boot_part=$(lsblk /dev/nbd0p* --sort SIZE -no NAME,FSTYPE | grep -E 'ext4|xfs' | sed '$d' | tail -1 | cut -d' ' -f1) - efi_part=$(lsblk /dev/nbd0p* --sort SIZE -no NAME,FSTYPE | grep fat | tail -1 | cut -d' ' -f1) + vg=$(pvs | grep /dev/nbd0p | awk '{print $2}') + lvchange -ay "$vg" fi + # TODO: 系统分区应该是最后一个分区 + # 选择最大分区 + os_part=$(lsblk /dev/nbd0p* --sort SIZE -no NAME,FSTYPE | grep -E 'ext4|xfs' | tail -1 | awk '{print $1}') + efi_part=$(lsblk /dev/nbd0p* --sort SIZE -no NAME,PARTTYPE | grep -i "$EFI_UUID" | awk '{print $1}') + # 排除前两个,再选择最大分区 + # alma 9 boot 分区的类型不是规定的 uuid + # openeuler boot 分区是 fat 格式 + boot_part=$(lsblk /dev/nbd0p* --sort SIZE -no NAME,FSTYPE | grep -E 'ext4|xfs|fat' | awk '{print $1}' | + grep -vx "$os_part" | { + if [ -n "$efi_part" ]; then + grep -vx "$efi_part" + else + cat + fi + } | tail -1 | awk '{print $1}') + + if $is_lvm_image; then + os_part="mapper/$os_part" + fi + + lsblk -f /dev/nbd0 -o +PARTTYPE + echo "Part OS: $os_part" + echo "Part EFI: $efi_part" + echo "Part Boot: $boot_part" + # 分区寻找方式 - # 系统/分区 rootfs efi + # 系统/分区 cmdline:root fstab:efi # rocky LABEL=rocky LABEL=EFI # ubuntu PARTUUID LABEL=UEFI # 其他el/ol UUID UUID @@ -2240,10 +2348,6 @@ install_qcow_by_copy() { swapon /dev/$xda*3 modify_el_ol() { - # redhat 使用用户提供的 qcow2 镜像,无法提前知道版本号 - # 因此需要从镜像读取版本号 - releasever=$(awk -F: '{ print $5 }' /os/etc/system-release-cpe) - # resolv.conf cp_resolv_conf /os @@ -2253,6 +2357,15 @@ install_qcow_by_copy() { # 部分镜像例如 centos7 要手动删除 machine-id truncate_machine_id /os + # el7 yum 可能会使用 ipv6,即使没有 ipv6 网络 + if [ "$releasever" = 7 ]; then + if [ "$(cat /dev/netconf/eth*/ipv6_has_internet | sort -u)" = 0 ]; then + echo 'ip_resolve=4' >>/os/etc/yum.conf + fi + fi + + # anolis 7 镜像自带 nm + # 删除云镜像自带的 dhcp 配置,防止歧义 # clout-init 网络配置在 /etc/sysconfig/network-scripts/ rm -rf /os/etc/NetworkManager/system-connections/*.nmconnection @@ -2272,14 +2385,21 @@ EOF sed -i '/[[:space:]]\/boot[[:space:]]/d' /os/etc/fstab sed -i '/[[:space:]]swap[[:space:]]/d' /os/etc/fstab - # oracle linux 系统盘从 lvm 改成 uuid 挂载 - sed -i "s,/dev/mapper/vg_main-lv_root,UUID=$os_part_uuid," /os/etc/fstab + # os_part 变量: + # mapper/vg_main-lv_root + # mapper/opencloudos-root + + # oracle/opencloudos 系统盘从 lvm 改成 uuid 挂载 + sed -i "s,/dev/$os_part,UUID=$os_part_uuid," /os/etc/fstab if ls /os/boot/loader/entries/*.conf 2>/dev/null; then - sed -i "s,/dev/mapper/vg_main-lv_root,UUID=$os_part_uuid," /os/boot/loader/entries/*.conf + # options root=/dev/mapper/opencloudos-root ro console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=1800M-64G:256M,64G-128G:512M,128G-486G:768M,486G-972G:1024M,972G-:2048M rd.lvm.lv=opencloudos/root rhgb quiet + sed -i "s,/dev/$os_part,UUID=$os_part_uuid," /os/boot/loader/entries/*.conf fi - # oracle linux 移除 lvm cmdline + # oracle/opencloudos 移除 lvm cmdline chroot /os grubby --update-kernel ALL --remove-args "resume rd.lvm.lv" + # el7 上面那条 grubby 命令不能设置 /etc/default/grub + sed -i 's/rd.lvm.lv=[^ "]*//g' /os/etc/default/grub # fstab 添加 efi 分区 if is_efi; then @@ -2312,7 +2432,9 @@ EOF # 只有centos 和 oracle x86_64 镜像没有efi,其他系统镜像已经从efi分区复制了文件 if [ -z "$efi_part" ]; then remove_grub_conflict_files - chroot_dnf install efibootmgr grub2-efi shim + # openeuler 自带 grub2-efi-ia32,此时安装 grub2-efi 提示已经安装了 grub2-efi-ia32,不会继续安装 grub2-efi-x64 + [ "$(uname -m)" = x86_64 ] && arch=x64 || arch=aa64 + chroot_dnf install efibootmgr grub2-efi-$arch shim-$arch fi else # bios @@ -2323,7 +2445,9 @@ EOF # blscfg 启动项 # rocky/alma镜像是独立的boot分区,但我们不是 # 因此要添加boot目录 - if [ -d /os/boot/loader/entries/ ] && ! grep -q 'initrd /boot/' /os/boot/loader/entries/*.conf; then + if ls /os/boot/loader/entries/*.conf 2>/dev/null && + ! grep -q 'initrd /boot/' /os/boot/loader/entries/*.conf; then + sed -i -E 's,((linux|initrd) /),\1boot/,g' /os/boot/loader/entries/*.conf fi @@ -2333,9 +2457,16 @@ EOF distro_efi=$(cd /os/boot/efi/EFI/ && ls -d -- * | grep -Eiv BOOT) fi + is_grub_efi_load_config_from_os() { + { [ "$distro" = openeuler ] && ! [ "$releasever" = 20.03 ]; } || + [ "$releasever" -ge 9 ] + } + # efi 分区 grub.cfg + # >=34.24 # https://github.com/rhinstaller/anaconda/blob/346b932a26a19b339e9073c049b08bdef7f166c3/pyanaconda/modules/storage/bootloader/efi.py#L198 - if is_efi && [ "$releasever" -ge 9 ]; then + # https://github.com/rhinstaller/anaconda/commit/15c3b2044367d375db6739e8b8f419ef3e17cae7 + if is_efi && is_grub_efi_load_config_from_os; then cat </os/boot/efi/EFI/$distro_efi/grub.cfg search --no-floppy --fs-uuid --set=dev $os_part_uuid set prefix=(\$dev)/boot/grub2 @@ -2345,9 +2476,10 @@ EOF fi # 主 grub.cfg - if is_efi && [ "$releasever" -le 8 ]; then + if is_efi && ! is_grub_efi_load_config_from_os; then chroot /os/ grub2-mkconfig -o /boot/efi/EFI/$distro_efi/grub.cfg else + # --update-bls-cmdline chroot /os/ grub2-mkconfig -o /boot/grub2/grub.cfg fi @@ -2449,8 +2581,19 @@ EOF restore_resolv_conf $os_dir } + # anolis/openeuler/opencloudos 可能要安装 cloud-init + # opencloudos 无法使用 chroot $os_dir command -v xxx + # chroot: failed to run command ‘command’: No such file or directory + if is_have_cmd_on_disk $os_dir rpm && + ! is_have_cmd_on_disk $os_dir cloud-init; then + + cp_resolv_conf $os_dir + chroot_dnf install cloud-init + restore_resolv_conf $os_dir + fi + # cloud-init - download_cloud_init_config /os + download_cloud_init_config $os_dir case "$distro" in ubuntu) modify_ubuntu ;; @@ -3440,7 +3583,7 @@ if is_use_cloud_image; then create_part download_qcow case "$distro" in - centos | alma | rocky | oracle | redhat) + centos | alma | rocky | oracle | redhat | anolis | opencloudos | openeuler) # 这几个系统云镜像系统盘是8~9g xfs,而我们的目标是能在5g硬盘上运行,因此改成复制系统文件 install_qcow_by_copy ;;