From a6be7587a3c7275f6ede44e51ad998229a9c86fd Mon Sep 17 00:00:00 2001 From: bin456789 Date: Thu, 25 May 2023 20:15:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=87=8D=E8=A3=85=E5=88=B0?= =?UTF-8?q?=20windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Autounattend.xml | 140 ++++++++++++++++++++++++++++++++ README.md | 36 +++++++-- reinstall.sh | 33 ++++++-- resize.bat | 2 + trans.sh | 203 +++++++++++++++++++++++++++++++++++++---------- 5 files changed, 360 insertions(+), 54 deletions(-) create mode 100644 Autounattend.xml create mode 100644 resize.bat diff --git a/Autounattend.xml b/Autounattend.xml new file mode 100644 index 0000000..b0b7b52 --- /dev/null +++ b/Autounattend.xml @@ -0,0 +1,140 @@ + + + + + + true + + OnError + + + + + OnError + + 0 + false + + + 1 + 1 + FAT32 + + + 2 + 2 + + + 3 + 3 + NTFS + + + + + + OnError + + + + + + /IMAGE/NAME + %image_name% + + + OnError + + 0 + 3 + + + + + + 1 + reg add HKLM\System\Setup\LabConfig /v BypassTPMCheck /t reg_dword /d 0x00000001 /f + + + 2 + reg add HKLM\System\Setup\LabConfig /v BypassSecureBootCheck /t reg_dword /d 0x00000001 /f + + + 3 + reg add HKLM\System\Setup\LabConfig /v BypassRAMCheck /t reg_dword /d 0x00000001 /f + + + 4 + reg add HKLM\System\Setup\LabConfig /v BypassStorageCheck /t reg_dword /d 0x00000001 /f + + + 5 + reg add HKLM\System\Setup\LabConfig /v BypassCPUCheck /t reg_dword /d 0x00000001 /f + + + + + %locale% + %locale% + %locale% + %locale% + + + + + X:\virtio + + + + + + + + + 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> + <RunSynchronousCommand wcm:action="add"> + <Path>net user Administrator /active:yes</Path> + <Order>1</Order> + </RunSynchronousCommand> + <RunSynchronousCommand wcm:action="add"> + <Order>2</Order> + <Path>xcopy D:\resize.bat C:\Windows\Temp\</Path> + </RunSynchronousCommand> + <RunSynchronousCommand wcm:action="add"> + <Order>3</Order> + <Path>C:\Windows\Temp\resize.bat</Path> + </RunSynchronousCommand> + </RunSynchronous> + </component> + <component name="Microsoft-Windows-TerminalServices-LocalSessionManager" 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"> + <fDenyTSConnections>false</fDenyTSConnections> + </component> + <component name="Networking-MPSSVC-Svc" 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"> + <FirewallGroups> + <FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop"> + <Profile>all</Profile> + <Group>@FirewallAPI.dll,-28752</Group> + <Active>true</Active> + </FirewallGroup> + </FirewallGroups> + </component> + <component name="Microsoft-Windows-powercpl" 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"> + <PreferredPlan>8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c</PreferredPlan> + </component> + </settings> +</unattend> diff --git a/README.md b/README.md index 2e2ee83..38a4016 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,25 @@ #### 亮点: ``` -使用官方安装方式,非第三方 DD 镜像,更安全 +使用官方安装方式,非第三方 dd 镜像,更安全 支持 BIOS/EFI 机器,支持 ARM 机器 可能是第一个支持在 1g 内存上安装 红帽 7/8/9 系列的脚本 可能是第一个支持重装到 ubuntu 22.04 的脚本 可能是第一个支持重装到 alpine 的脚本 +可能是第一个支持重装到 Windows 的脚本(不算 dd 的话) ``` #### 使用: ``` +下载: curl -O https://raw.githubusercontent.com/bin456789/reinstall/main/reinstall.sh -bash reinstall.sh centos-7 或其他系统 + +安装 Linux: +bash reinstall.sh centos-7 (或其他系统) + +安装 Windows: +bash reinstall.sh windows --iso=https://archive.org/download/xxx/zh-cn_windows_10_enterprise_ltsc_2021_x64_dvd_033b7312.iso --image-name='Windows 10 Enterprise LTSC 2021' (或其他系统) + +重启: reboot ``` #### 支持重装到: @@ -24,19 +33,32 @@ fedora-36/37/38 ubuntu-20.04/22.04 alpine-3.16/3.17/3.18 debian-10/11 +windows (见下方注意事项) +``` +#### Windows 注意事项: +``` +只支持 UEFI 引导的机器,已测试成功的系统有 7 10 11,其他系统不保证成功 +安装 Windows 需要以下参数 +--iso iso 链接,不需要提前添加 virtio 驱动 +--image-name 系统全名,例如: + Windows 7 Ultimate + Windows 10 Enterprise LTSC 2021 + Windows 11 Pro ``` #### 内存要求: ``` -debian 384m -centos/alma/rocky/fedora 1g +debian 384M +centos/alma/rocky/fedora 1G alpine ? ubuntu ? +windows 1G ``` #### 网络要求: ``` 要求有 IPv4、DHCPv4 ``` #### 默认用户名 / 密码: - ``` - root 123@@@ - ```` \ No newline at end of file +``` +root 123@@@ +administrator 123@@@ +```` \ No newline at end of file diff --git a/reinstall.sh b/reinstall.sh index 60719b4..3618389 100644 --- a/reinstall.sh +++ b/reinstall.sh @@ -3,7 +3,7 @@ confhome=https://raw.githubusercontent.com/bin456789/reinstall/main localtest_confhome=http://192.168.253.1 usage_and_exit() { - echo "Usage: reinstall.sh centos-7/8/9 alma-8/9 rocky-8/9 fedora-36/37/38 ubuntu-20.04/22.04 alpine-3.16/3.17/3.18 debian-10/11" + echo "Usage: reinstall.sh centos-7/8/9 alma-8/9 rocky-8/9 fedora-36/37/38 ubuntu-20.04/22.04 alpine-3.16/3.17/3.18 debian-10/11 windows" exit 1 } @@ -23,10 +23,10 @@ setos() { setos_alpine() { if [ "$localtest" = 1 ]; then - mirror=$confhome/alpine-netboot-3.17.3-x86_64/boot + mirror=$confhome/alpine-netboot-3.18.0-x86_64/boot eval ${step}_vmlinuz=$mirror/vmlinuz-lts eval ${step}_initrd=$mirror/initramfs-lts - eval ${step}_repo=https://mirrors.aliyun.com/alpine/v3.17/main + eval ${step}_repo=https://mirrors.aliyun.com/alpine/v$releasever/main eval ${step}_modloop=$mirror/modloop-lts else # 不要用https 因为甲骨文云arm initramfs阶段不会从硬件同步时钟,导致访问https出错 @@ -87,6 +87,15 @@ setos() { eval ${step}_ks=$confhome/user-data } + setos_windows() { + if [ -z "$iso" ] || [ -z "$image_name" ]; then + echo "Install Windows need --iso --image-name" + exit 1 + fi + eval "${step}_iso='$iso'" + eval "${step}_image_name='$image_name'" + } + setos_redhat() { if [ "$localtest" = 1 ]; then mirror=$confhome/$releasever/ @@ -122,13 +131,14 @@ setos() { ubuntu) setos_ubuntu ;; alpine) setos_alpine ;; debian) setos_debian ;; + windows) setos_windows ;; *) setos_redhat ;; esac } # 检查是否为正确的系统名 verify_os_string() { - for os in 'centos-7|8|9' 'alma|rocky-8|9' 'fedora-36|37|38' 'ubuntu-20.04|22.04' 'alpine-3.16|3.17|3.18' 'debian-10|11|12'; do + for os in 'centos-7|8|9' 'alma|rocky-8|9' 'fedora-36|37|38' 'ubuntu-20.04|22.04' 'alpine-3.16|3.17|3.18' 'debian-10|11|12' 'windows-'; do ds=$(echo $os | cut -d- -f1) vers=$(echo $os | cut -d- -f2 | sed 's \. \\\. g') finalos=$(echo "$@" | tr '[:upper:]' '[:lower:]' | sed -n -E "s,^($ds)[ :-]?($vers)$,\1:\2,p") @@ -198,7 +208,7 @@ if [ "$EUID" -ne 0 ]; then exit 1 fi -if ! opts=$(getopt -a -n $0 --options l --long localtest -- "$@"); then +if ! opts=$(getopt -a -n $0 --options l --long localtest,iso:,image-name: -- "$@"); then usage_and_exit fi @@ -210,6 +220,14 @@ while true; do confhome=$localtest_confhome shift ;; + --iso) + iso=$2 + shift 2 + ;; + --image-name) + image_name=$2 + shift 2 + ;; --) shift break @@ -243,6 +261,7 @@ esac # el7 aarch64 <1.5g if [ "$distro" = "ubuntu" ] || [ "$distro" = "alpine" ] || + [ "$distro" = "windows" ] || { [ "$distro_like" = "redhat" ] && [ $releasever -ge 8 ] && [ $ram_size -lt 2048 ]; } || { [ "$distro_like" = "redhat" ] && [ $releasever -eq 7 ] && [ $ram_size -lt 1536 ] && [ $basearch = "aarch64" ]; }; then # 安装alpine时,使用指定的版本。 alpine作为中间系统时,使用 3.18 @@ -270,7 +289,7 @@ build_finalos_cmdline() { value=${!key} key=${key#finalos_} if [ -n "$value" ] && [ $key != "mirrorlist" ]; then - finalos_cmdline+=" finalos.$key=$value" + finalos_cmdline+=" finalos.$key='$value'" fi done } @@ -279,7 +298,7 @@ build_extra_cmdline() { for key in localtest confhome; do value=${!key} if [ -n "$value" ]; then - extra_cmdline+=" extra.$key=$value" + extra_cmdline+=" extra.$key='$value'" fi done diff --git a/resize.bat b/resize.bat new file mode 100644 index 0000000..d003b6a --- /dev/null +++ b/resize.bat @@ -0,0 +1,2 @@ +for /f "tokens=2" %%a in ('echo list vol ^| diskpart ^| findstr /i "installer"') do (echo select disk 0 & echo select vol %%a & echo delete partition) | diskpart +for /f "tokens=2" %%a in ('echo list vol ^| diskpart ^| findstr "\<C\>"') do (echo select disk 0 & echo select vol %%a & echo extend) | diskpart \ No newline at end of file diff --git a/trans.sh b/trans.sh index d06cd9c..9dc6208 100644 --- a/trans.sh +++ b/trans.sh @@ -7,11 +7,22 @@ # script -f/dev/tty0 exec >/dev/tty0 2>&1 +add_community_repo() { + alpine_ver=$(cut -d. -f1,2 </etc/alpine-release) + echo http://dl-cdn.alpinelinux.org/alpine/v$alpine_ver/community >>/etc/apk/repositories +} + # 提取 finalos/extra 到变量 for prefix in finalos extra; do - for var in $(grep -o "\b$prefix\.[^ ]*" /proc/cmdline | xargs); do - eval "$(echo $var | sed -E "s/$prefix\.([^=]*)=(.*)/\1='\2'/")" - done + while read -r line; do + if [ -n "$line" ]; then + key=$(echo $line | cut -d= -f1) + value=$(echo $line | cut -d= -f2-) + eval "$key='$value'" + fi + done <<EOF +$(xargs -n1 </proc/cmdline | grep "^$prefix" | sed "s/^$prefix\.//") +EOF done # 找到主硬盘 @@ -57,8 +68,7 @@ if [ "$distro" = "alpine" ]; then # seedrng | boot # 添加 virt-what 用到的社区仓库 - alpine_ver=$(cut -d. -f1,2 </etc/alpine-release) - echo http://dl-cdn.alpinelinux.org/alpine/v$alpine_ver/community >>/etc/apk/repositories + add_community_repo # 如果是 vm 就用 virt 内核 cp /etc/apk/world /tmp/world.old @@ -129,42 +139,69 @@ disk_2t=$((2 * 1024 * 1024 * 1024 * 1024)) # 对于红帽系是临时分区表,安装时除了 installer 分区,其他分区会重建为默认的大小 # 对于ubuntu是最终分区表,因为 ubuntu 的安装器不能调整个别分区,只能重建整个分区表 # {xda}*1 星号用于 nvme0n1p1 的字母 p -if [ -d /sys/firmware/efi ]; then - # efi - apk add dosfstools - parted /dev/$xda -s -- \ - mklabel gpt \ - mkpart '" "' fat32 1MiB 1025MiB \ - mkpart '" "' ext4 1025MiB -2GiB \ - mkpart '" "' ext4 -2GiB 100% \ - set 1 boot on - update_part /dev/$xda - mkfs.fat -F 32 -n efi /dev/${xda}*1 #1 efi - mkfs.ext4 -F -L os /dev/${xda}*2 #2 os - mkfs.ext4 -F -L installer /dev/${xda}*3 #3 installer -elif [ "$disk_size" -ge "$disk_2t" ]; then - # bios 2t - parted /dev/$xda -s -- \ - mklabel gpt \ - mkpart '" "' ext4 1MiB 2MiB \ - mkpart '" "' ext4 2MiB -2GiB \ - mkpart '" "' ext4 -2GiB 100% \ - set 1 bios_grub on - update_part /dev/$xda - echo #1 bios_boot - mkfs.ext4 -F -L os /dev/${xda}*2 #2 os - mkfs.ext4 -F -L installer /dev/${xda}*3 #3 installer +if [ "$distro" = windows ]; then + if [ -d /sys/firmware/efi ]; then + add_community_repo + apk add dosfstools ntfs-3g ntfs-3g-progs fuse virt-what wimlib rsync efibootmgr + modprobe fuse + parted /dev/$xda -s -- \ + mklabel gpt \ + mkpart '" "' fat32 1MiB 1025MiB \ + mkpart '" "' fat32 1025MiB 1041MiB \ + mkpart '" "' ext4 1041MiB -6GiB \ + mkpart '" "' ntfs -6GiB 100% \ + set 1 boot on \ + set 2 msftres on \ + set 3 msftdata on + update_part /dev/$xda + mkfs.fat -F 32 -n efi /dev/${xda}*1 #1 efi + echo #2 msr + mkfs.ext4 -F -L os /dev/${xda}*3 #3 os + mkfs.ntfs -f -F -L installer /dev/${xda}*4 #4 installer + else + echo "This script not support install windows on none-efi system" + sleep 1m + exec reboot + fi else - # bios - parted /dev/$xda -s -- \ - mklabel msdos \ - mkpart primary ext4 1MiB -2GiB \ - mkpart primary ext4 -2GiB 100% \ - set 1 boot on - update_part /dev/$xda - mkfs.ext4 -F -L os /dev/${xda}*1 #1 os - mkfs.ext4 -F -L installer /dev/${xda}*2 #2 installer + if [ -d /sys/firmware/efi ]; then + # efi + apk add dosfstools + parted /dev/$xda -s -- \ + mklabel gpt \ + mkpart '" "' fat32 1MiB 1025MiB \ + mkpart '" "' ext4 1025MiB -2GiB \ + mkpart '" "' ext4 -2GiB 100% \ + set 1 boot on + update_part /dev/$xda + mkfs.fat -F 32 -n efi /dev/${xda}*1 #1 efi + mkfs.ext4 -F -L os /dev/${xda}*2 #2 os + mkfs.ext4 -F -L installer /dev/${xda}*3 #3 installer + elif [ "$disk_size" -ge "$disk_2t" ]; then + # bios 2t + parted /dev/$xda -s -- \ + mklabel gpt \ + mkpart '" "' ext4 1MiB 2MiB \ + mkpart '" "' ext4 2MiB -2GiB \ + mkpart '" "' ext4 -2GiB 100% \ + set 1 bios_grub on + update_part /dev/$xda + echo #1 bios_boot + mkfs.ext4 -F -L os /dev/${xda}*2 #2 os + mkfs.ext4 -F -L installer /dev/${xda}*3 #3 installer + else + # bios + parted /dev/$xda -s -- \ + mklabel msdos \ + mkpart primary ext4 1MiB -2GiB \ + mkpart primary ext4 -2GiB 100% \ + set 1 boot on + update_part /dev/$xda + mkfs.ext4 -F -L os /dev/${xda}*1 #1 os + mkfs.ext4 -F -L installer /dev/${xda}*2 #2 installer + fi fi + update_part /dev/$xda # 挂载主分区 @@ -177,8 +214,94 @@ mount /dev/disk/by-label/efi /os/boot/efi mkdir -p /os/installer mount /dev/disk/by-label/installer /os/installer -# 安装 grub2 basearch=$(uname -m) +case "$basearch" in +"x86_64") basearch_alt=amd64 ;; +"aarch64") basearch_alt=arm64 ;; +esac + +# 目前只支持 efi +# shellcheck disable=SC2154 +if [ "$distro" = "windows" ] && [ -d /sys/firmware/efi/ ]; then + download $iso /os/windows.iso + mkdir /iso + mount /os/windows.iso /iso + + # 下载 virtio 驱动 + if [ "$(virt-what)" = kvm ]; then + case $(echo "$image_name" | tr '[:upper:]' '[:lower:]') in + 'windows server 2022'*) sys=2k22 ;; + 'windows server 2019'*) sys=2k19 ;; + 'windows server 2016'*) sys=2k16 ;; + 'windows server 2012 R2'*) sys=2k12R2 ;; + 'windows server 2012'*) sys=2k12 ;; + 'windows server 2008 R2'*) sys=2k8R2 ;; + 'windows server 2008'*) sys=2k8 ;; + 'windows 11'*) sys=w11 ;; + 'windows 10'*) sys=w10 ;; + 'windows 8.1'*) sys=w8.1 ;; + 'windows 8'*) sys=w8 ;; + 'windows 7'*) sys=w7 ;; + esac + + if [ $sys = w7 ]; then + # https://github.com/virtio-win/virtio-win-pkg-scripts/issues/40 + # https://tcler.github.io/2022/01/24/virtio-win-for-windows-7/ + dir=archive-virtio/virtio-win-0.1.189-1 + else + dir=stable-virtio + fi + download https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/$dir/virtio-win.iso /os/virtio-win.iso + mkdir /virtio + mount /os/virtio-win.iso /virtio + fi + + # 复制启动文件到efi分区 + mkdir -p /os/boot/efi/sources/ + /bin/cp -rv /iso/boot* /iso/efi/ /os/boot/efi/ + /bin/cp -rv /iso/sources/boot.wim /os/boot/efi/sources/ + + # 复制全部文件到installer分区,除了 boot.wim + rsync -rv --exclude=/sources/boot.wim /iso/* /os/installer/ + + # 合并分区脚本 + download $confhome/resize.bat /os/installer/resize.bat + + # 修改应答文件 + download $confhome/Autounattend.xml /tmp/Autounattend.xml + locale=$(wiminfo /os/boot/efi/sources/boot.wim | grep 'Default Language' | head -1 | awk '{print $NF}') + sed -i "s|%arch%|$basearch_alt|; s|%image_name%|$image_name|; s|%locale%|$locale|; s|%confhome%|$confhome|" /tmp/Autounattend.xml + + + mkdir /wim + wimmountrw /os/boot/efi/sources/boot.wim 2 /wim/ + + # virtio 驱动 + if [ -d /virtio ]; then + mkdir /wim/virtio + find /virtio \ + -ipath "*/$sys/$basearch_alt/*" \ + -not -iname '*.pdb' \ + -not -iname '*.doc' \ + -exec /bin/cp -r {} /wim/virtio/ \; + fi + + # win7 要添加 bootx64.efi 到 efi 目录 + [ $basearch = x86_64 ] && boot_efi=bootx64.efi || boot_efi=bootaa64.efi + if [ ! -e /os/boot/efi/efi/boot/$boot_efi ]; then + mkdir -p /os/boot/efi/efi/boot/ + cp /wim/Windows/Boot/EFI/bootmgfw.efi /os/boot/efi/efi/boot/$boot_efi + fi + + # 应答文件 + cp /tmp/Autounattend.xml /wim/ + wimunmount --commit /wim/ + + efibootmgr -c -L "Windows Installer" -d /dev/$xda -p1 -l "\\EFI\\boot\\$boot_efi" + exec reboot +fi + +# 安装 grub2 if [ -d /sys/firmware/efi/ ]; then # 注意低版本的grub无法启动f38 arm的内核 # https://forums.fedoraforum.org/showthread.php?330104-aarch64-pxeboot-vmlinuz-file-format-changed-broke-PXE-installs