diff --git a/cloud-init.yaml b/cloud-init.yaml index 0c88953..8107be2 100644 --- a/cloud-init.yaml +++ b/cloud-init.yaml @@ -16,8 +16,7 @@ chpasswd: password: 123@@@ type: text runcmd: - # arch 没有 /etc/ssh/sshd_config.d/ 文件夹 - # opensuse tumbleweed 有 /etc/ssh/sshd_config.d/ 文件夹,但没有 /etc/ssh/sshd_config,但有/usr/etc/ssh/sshd_config + # opensuse tumbleweed 有 /etc/ssh/sshd_config.d/ 文件夹,没有 /etc/ssh/sshd_config,有/usr/etc/ssh/sshd_config - grep 'Include.*/etc/ssh/sshd_config.d' /etc/ssh/sshd_config && mkdir -p /etc/ssh/sshd_config.d && echo "PermitRootLogin yes" >/etc/ssh/sshd_config.d/01-permitrootlogin.conf || echo "PermitRootLogin yes" >>/etc/ssh/sshd_config - systemctl restart sshd - touch /etc/cloud/cloud-init.disabled diff --git a/reinstall.bat b/reinstall.bat index c85e9ed..e0e6f85 100644 --- a/reinstall.bat +++ b/reinstall.bat @@ -80,13 +80,13 @@ if not exist !tags! ( :: 安装 Cygwin set site=!mirror!!dir! - %tmp%\setup-cygwin.exe --allow-unsupported-windows^ - --quiet-mode^ - --only-site^ - --site !site!^ - --root %SystemDrive%\cygwin^ - --local-package-dir %tmp%\cygwin-local-package-dir^ - --packages !pkgs!^ + %tmp%\setup-cygwin.exe --allow-unsupported-windows ^ + --quiet-mode ^ + --only-site ^ + --site !site! ^ + --root %SystemDrive%\cygwin ^ + --local-package-dir %tmp%\cygwin-local-package-dir ^ + --packages !pkgs! ^ && type nul >!tags! ) diff --git a/reinstall.sh b/reinstall.sh index 44c6b9b..f338632 100644 --- a/reinstall.sh +++ b/reinstall.sh @@ -278,6 +278,7 @@ is_virt() { if is_have_cmd systemd-detect-virt && systemd-detect-virt -v; then _is_virt=true fi + if [ -z "$_is_virt" ]; then # debian 安装 virt-what 不会自动安装 dmidecode,因此结果有误 install_pkg dmidecode virt-what @@ -317,7 +318,7 @@ setos() { setos_alpine() { is_virt && flavour=virt || flavour=lts - # alpine aarch64 3.16/3.17 lts 才有直连链接 + # alpine aarch64 3.16/3.17 virt 没有直连链接 if [ "$basearch" = aarch64 ] && { [ "$releasever" = 3.16 ] || [ "$releasever" = 3.17 ]; }; then flavour=lts @@ -331,8 +332,8 @@ setos() { fi eval ${step}_vmlinuz=$mirror/releases/$basearch/netboot/vmlinuz-$flavour eval ${step}_initrd=$mirror/releases/$basearch/netboot/initramfs-$flavour - eval ${step}_repo=$mirror/main eval ${step}_modloop=$mirror/releases/$basearch/netboot/modloop-$flavour + eval ${step}_repo=$mirror/main } setos_debian() { @@ -726,15 +727,18 @@ install_pkg() { esac } + is_need_rebuild() { + cmd=$1 + # gentoo 默认编译的 unsquashfs 不支持 xz + if [ "$cmd" = unsquashfs ] && is_have_cmd emerge && ! unsquashfs |& grep -w xz; then + echo "unsquashfs not supported xz. rebuilding." + return 0 + fi + return 1 + } + for cmd in "$@"; do - if ! is_have_cmd $cmd || - { - # gentoo 默认编译的 unsquashfs 不支持 xz - [ "$cmd" = unsquashfs ] && - is_have_cmd emerge && - ! unsquashfs |& grep -w xz && - echo "unsquashfs not supported xz. need rebuild." - }; then + if ! is_have_cmd $cmd || is_need_rebuild $cmd; then if ! find_pkg_mgr; then error_and_exit "Can't find compatible package manager. Please manually install $cmd." fi @@ -799,7 +803,8 @@ check_ram() { is_efi() { if is_in_windows; then - bcdedit | grep -q '^path.*\.efi' + # bcdedit | grep -qi '^path.*\.efi' + mountvol | grep -q --text 'EFI' else [ -d /sys/firmware/efi ] fi @@ -976,7 +981,7 @@ add_efi_entry_in_windows() { get_maybe_efi_dirs_in_linux() { # arch云镜像efi分区挂载在/efi,且使用 autofs,挂载后会有两个 /efi 条目 - mount | awk '$5=="vfat" || $5=="autofs" {print $3}' | grep -E '/boot|/efi' | sort | uniq + mount | awk '$5=="vfat" || $5=="autofs" {print $3}' | grep -E '/boot|/efi' | sort -u } get_disk_by_part() { @@ -1045,7 +1050,7 @@ install_grub_linux_efi() { grub_efi=grubx64.efi fi - # fedora x86_64 的 efi 无法识别 opensuse tumbleweed 的 btrfs + # fedora x86_64 的 efi 无法识别 opensuse tumbleweed 的 xfs # opensuse tumbleweed aarch64 的 efi 无法识别 alpine 3.19 的内核 if [ "$basearch" = aarch64 ]; then efi_distro=fedora @@ -1053,13 +1058,15 @@ install_grub_linux_efi() { efi_distro=opensuse fi + # 不要用 download.opensuse.org 和 download.fedoraproject.org + # 因为 ipv6 访问有时跳转到 ipv4 地址,造成 ipv6 only 机器无法下载 if [ "$efi_distro" = fedora ]; then fedora_ver=39 if is_in_china; then mirror=https://mirrors.tuna.tsinghua.edu.cn/fedora else - mirror=https://download.fedoraproject.org/pub/fedora/linux + mirror=https://mirror.fcix.net/fedora/linux fi curl -Lo /tmp/$grub_efi $mirror/releases/$fedora_ver/Everything/$basearch/os/EFI/BOOT/$grub_efi @@ -1067,7 +1074,7 @@ install_grub_linux_efi() { if is_in_china; then mirror=https://mirror.sjtu.edu.cn/opensuse else - mirror=https://download.opensuse.org + mirror=https://mirror.fcix.net/opensuse fi file=tumbleweed/repo/oss/EFI/BOOT/grub.efi @@ -1102,7 +1109,7 @@ install_grub_win() { # 设置 grub prefix 为c盘根目录 # 运行 grub-probe 会改变cmd窗口字体 - prefix=$($grub-probe -t drive $c: | sed 's,.*PhysicalDrive,(hd,' | sed 's,\r,,')/ + prefix=$($grub-probe -t drive $c: | sed 's|.*PhysicalDrive|(hd|' | del_cr)/ echo $prefix # 安装 grub @@ -1186,9 +1193,11 @@ echo_tmp_ttys() { } get_entry_name() { - printf 'reinstall (%s%s%s)' "$distro" \ - "$([ -n "$releasever" ] && printf ' %s' "$releasever")" \ - "$([ "$distro" = alpine ] && [ "$hold" = 1 ] && printf ' Live OS')" + printf 'reinstall (' + printf '%s' "$distro" + [ -n "$releasever" ] && printf ' %s' "$releasever" + [ "$distro" = alpine ] && [ "$hold" = 1 ] && printf ' Live OS' + printf ')' } # shellcheck disable=SC2154 @@ -1369,10 +1378,13 @@ EOF # 脚本入口 # 检查 root -if ! is_in_windows; then +if is_in_windows; then + if ! openfiles >/dev/null 2>&1; then + error_and_exit "Please run as administrator." + fi +else if [ "$EUID" -ne 0 ]; then - info "Please run as root." - exit 1 + error_and_exit "Please run as root." fi fi @@ -1568,8 +1580,8 @@ fi # 将内核/netboot.xyz.lkrn 放到正确的位置 if is_use_grub; then if is_in_windows; then - mv /reinstall-vmlinuz /cygdrive/$c/ - is_have_initrd && mv /reinstall-initrd /cygdrive/$c/ + cp -f /reinstall-vmlinuz /cygdrive/$c/ + is_have_initrd && cp -f /reinstall-initrd /cygdrive/$c/ else if is_os_in_btrfs && is_os_in_subvol; then cp_to_btrfs_root /reinstall-vmlinuz @@ -1584,8 +1596,9 @@ if is_use_grub; then if is_in_windows; then install_grub_win else - # linux aarch64 efi 要用去除了内核 magic number 校验的 grub - # 为了方便测试,linux x86 efi 也是用外部 grub + # linux aarch64 原系统的 grub 可能无法启动 alpine 3.19 的内核 + # 要用去除了内核 magic number 校验的 grub + # 为了方便测试,linux x86 efi 也采用外部 grub if is_efi; then install_grub_linux_efi fi @@ -1623,11 +1636,12 @@ if is_use_grub; then fi fi - # 判断用 linux 还是 linuxefi + # 判断用 linux 还是 linuxefi(主要是红帽系) # 现在 efi 用下载的 grub,因此不需要判断 linux 或 linuxefi if false && is_use_local_grub; then # 在x86 efi机器上,不同版本的 grub 可能用 linux 或 linuxefi 加载内核 # 通过检测原有的条目有没有 linuxefi 字样就知道当前 grub 用哪一种 + # 也可以检测 /etc/grub.d/10_linux if [ -d /boot/loader/entries/ ]; then entries="/boot/loader/entries/" fi diff --git a/trans.sh b/trans.sh index 31e1f13..0972c81 100644 --- a/trans.sh +++ b/trans.sh @@ -67,7 +67,6 @@ is_have_cmd() { download() { url=$1 path=$2 - echo $url # 有ipv4地址无ipv4网关的情况下,aria2可能会用ipv4下载,而不是ipv6 # axel 在 lightsail 上会占用大量cpu @@ -96,12 +95,25 @@ download() { # 阿里云源检测 user-agent 禁止 axel/aria2 下载 # aria2 默认 --max-tries 5 - stdbuf -o0 -e0 \ - aria2c -x4 \ - --allow-overwrite=true \ - --summary-interval=0 \ - --user-agent=Wget/1.21.1 \ - $save $url + + # 默认 --max-tries=5,但以下情况服务器出错,aria2不会重试,而是直接返回错误 + # 因此添加 for 循环 + # [ERROR] CUID#7 - Download aborted. URI=https://aka.ms/manawindowsdrivers + # Exception: [AbstractCommand.cc:351] errorCode=1 URI=https://aka.ms/manawindowsdrivers + # -> [SocketCore.cc:1019] errorCode=1 SSL/TLS handshake failure: `not signed by known authorities or invalid' + + echo "$url" + for i in 1 2 3; do + if stdbuf -oL -eL \ + aria2c -x4 \ + --allow-overwrite=true \ + --summary-interval=0 \ + --user-agent=Wget/1.21.1 \ + --max-tries 1 \ + $save $url; then + return + fi + done } update_part() { @@ -1284,7 +1296,7 @@ modify_linux() { # 修复 fedora 38 或以下用静态 ipv6 会掉线 # el 全系也用 NetworkManager,但他们的配置文件是 sysconfig,因此不受影响 # https://github.com/canonical/cloud-init/commit/5d440856cb6d2b4c908015fe4eb7227615c17c8b - if grep -E 'fedora:(37|38)' $os_dir/etc/os-release; then + if grep -E 'fedora:38' $os_dir/etc/os-release; then network_manager_py=$os_dir/usr/lib/python3.11/site-packages/cloudinit/net/network_manager.py && if ! grep '"static6": "manual",' $network_manager_py; then echo '"static6": "manual",' | insert_into_file $network_manager_py after '"static": "manual",' @@ -1405,7 +1417,11 @@ modify_os_on_disk() { return fi elif [ "$only_process" = windows ]; then - # find 有时会报 I/O error + # find 不是很聪明 + # find /mnt/c -iname windows -type d -maxdepth 1 + # find: /mnt/c/pagefile.sys: Permission denied + # find: /mnt/c/swapfile.sys: Permission denied + # shellcheck disable=SC2010 if ls -d /os/*/ | grep -i '/windows/' 2>/dev/null; then # 重新挂载为读写、忽略大小写 umount /os @@ -2115,7 +2131,8 @@ install_windows() { # 如果有重复的 Windows/System32 文件夹,会提示找不到 winload.exe 无法引导 # win7 win10 是 Windows/System32 # win2016 是 windows/system32 - system32_dir=$(ls -d /wim/*/*32) + # shellcheck disable=SC2010 + system32_dir=$(ls -d /wim/*/*32 | grep -i windows/system32) download $confhome/windows-setup.bat $system32_dir/startnet.cmd # 提交修改 boot.wim @@ -2323,9 +2340,6 @@ if [ "$hold" = 2 ]; then exit fi -# 让 web ssh 输出全部内容 -for i in $(seq 10); do - echo -done +# 让 web 输出全部内容 sleep 5 reboot diff --git a/windows-setup.bat b/windows-setup.bat index 1f58210..8f3e0fb 100644 --- a/windows-setup.bat +++ b/windows-setup.bat @@ -17,14 +17,17 @@ for %%F in ("X:\drivers\*.inf") do ( :: 等待加载分区 :: 没有 timeout 命令 :: 没有加载网卡驱动,无法用 ping 来等待 -echo wscript.sleep(5000) > sleep.vbs -cscript //nologo sleep.vbs +echo wscript.sleep(5000) > X:\sleep.vbs +cscript //nologo X:\sleep.vbs +del X:\sleep.vbs :: 判断 efi 还是 bios +:: 或者用 https://learn.microsoft.com/windows-hardware/manufacture/desktop/boot-to-uefi-mode-or-legacy-bios-mode +:: pe 下没有 mountvol echo list vol | diskpart | find "efi" && ( - set boot_type=efi + set BootType=efi ) || ( - set boot_type=bios + set BootType=bios ) :: 获取 installer 卷 id @@ -47,7 +50,7 @@ for /f "tokens=3" %%a in (X:\disk.txt) do ( del X:\disk.txt :: 重新分区/格式化 -(if "%boot_type%"=="efi" ( +(if "%BootType%"=="efi" ( echo select disk %DiskIndex% echo select part 1 diff --git a/windows.xml b/windows.xml index e94fa5a..7a6e1d3 100644 --- a/windows.xml +++ b/windows.xml @@ -1,5 +1,6 @@ + @@ -9,18 +10,6 @@ - - OnError - - %disk_id% - false - - - - - - OnError - @@ -54,6 +43,7 @@ + @@ -63,23 +53,7 @@ - - - - - 123@@@ - true</PlainText> - </AdministratorPassword> - </UserAccounts> - <OOBE> - <HideEULAPage>true</HideEULAPage> - <ProtectYourPC>3</ProtectYourPC> - <SkipMachineOOBE>true</SkipMachineOOBE> - <SkipUserOOBE>true</SkipUserOOBE> - </OOBE> - <TimeZone>China Standard Time</TimeZone> - </component> - </settings> + <settings pass="specialize"> <component name="Microsoft-Windows-Deployment" processorArchitecture="%arch%" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <RunSynchronous> @@ -130,4 +104,22 @@ <PreferredPlan>8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c</PreferredPlan> </component> </settings> + + <settings pass="oobeSystem"> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="%arch%" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <UserAccounts> + <AdministratorPassword> + <Value>123@@@</Value> + <PlainText>true</PlainText> + </AdministratorPassword> + </UserAccounts> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <ProtectYourPC>3</ProtectYourPC> + <SkipMachineOOBE>true</SkipMachineOOBE> + <SkipUserOOBE>true</SkipUserOOBE> + </OOBE> + <TimeZone>China Standard Time</TimeZone> + </component> + </settings> </unattend>