Compare commits

...

7 Commits

Author SHA1 Message Date
bin456789
0f147ed656
core: 不重要的优化 2025-02-21 00:30:36 +08:00
bin456789
c63889f32d
core: 更改地区检测网站
fixes #247
2025-02-21 00:30:36 +08:00
bin456789
739c75c2d1
windows: 通过文件检测是否有 sac 组件 2025-02-21 00:30:35 +08:00
bin456789
9732c3379a
windows: 避免将潜在的 Windows 11 Enterprise multi-session iso 识别成 Windows Server 2025-02-21 00:30:34 +08:00
bin456789
1bc6cf090b
fnos: 支持安装飞牛OS
fixes #256
2025-02-21 00:30:34 +08:00
bin456789
6263f994af
windows: 支持磁力链接下载 iso
fixes #268
2025-02-21 00:30:33 +08:00
bin456789
8e8bf610dc
ubuntu: 修复 apt install 没有把最佳内核标记为 manual 导致 apt autoremove 删除了所有内核 2025-02-20 21:39:37 +08:00
7 changed files with 500 additions and 148 deletions

View File

@ -15,7 +15,7 @@ One-Click Script to Reinstall System [中文](README.md)
## Highlights
- One-click Linux installation: Supports 17 common distributions.
- One-click Linux installation: Supports 18 common distributions.
- One-click Windows installation: Uses the official ISO for installation instead of custom images. The script automatically retrieves the ISO link and installs `Virtio` and other drivers.
- Supports installation in any direction, i.e., `Linux to Linux`, `Linux to Windows`, `Windows to Windows`, `Windows to Linux`
- No need to input IP parameters; automatically recognizes dynamic and static IPs, supports `/32`, `/128`, `gateway outside subnet`, `IPv6 only`, `dual NIC` and other special network configurations
@ -31,7 +31,7 @@ The original system can be any system listed in the table.
The system requirements for the target system are as follows:
| Target System | Version | Memory | Disk |
| System | Version | Memory | Disk |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | --------- | -----------------|
| <img width="16" height="16" src="https://www.alpinelinux.org/alpine-logo.ico" /> Alpine | 3.18, 3.19, 3.20, 3.21 | 256 MB | 1 GB |
| <img width="16" height="16" src="https://www.debian.org/favicon.ico" /> Debian | 9, 10, 11, 12 | 256 MB | 1 ~ 1.5 GB ^ |
@ -47,6 +47,7 @@ The system requirements for the target system are as follows:
| <img width="16" height="16" src="https://github.com/user-attachments/assets/99a542b6-6482-4086-addf-f192c06fef73" /> NixOS | 24.11 | 512 MB | 5 GB |
| <img width="16" height="16" src="https://archlinux.org/static/favicon.png" /> Arch | Rolling | 512 MB | 5 GB |
| <img width="16" height="16" src="https://www.gentoo.org/assets/img/logo/gentoo-g.png" /> Gentoo | Rolling | 512 MB | 5 GB |
| <img width="16" height="16" src="https://www.fnnas.com/favicon.ico" /> 飞牛 fnOS | Beta | 512 MB | 12 GB |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (DD) | Any | 512 MB | Depends on image |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (ISO) | Vista, 7, 8.x (Server 2008 - 2012 R2) | 512 MB | 25 GB |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (ISO) | 10, 11 (Server 2016 - 2025) | 1 GB | 25 GB |
@ -111,8 +112,9 @@ certutil -urlcache -f -split https://gitlab.com/bin456789/reinstall/-/raw/main/r
**All features** can be used on both Linux and Windows.
- on Linux, execute `bash reinstall.sh`
- on Windows, execute `.\reinstall.bat`
- on Linux, run `bash reinstall.sh ...`
- on Windows, first run `cmd`, then run `.\reinstall.bat ...`
- If the link in the parameter contains special characters, it should be enclosed in `""`, not `''`.
### Feature 1: Install <img width="16" height="16" src="https://www.kernel.org/theme/images/logos/favicon.png" /> Linux
@ -127,7 +129,7 @@ certutil -urlcache -f -split https://gitlab.com/bin456789/reinstall/-/raw/main/r
bash reinstall.sh anolis 7|8|23
opencloudos 8|9|23
rocky 8|9
redhat 8|9 --img='http://xxx.com/xxx.qcow2'
redhat 8|9 --img="http://xxx.com/xxx.qcow2"
oracle 8|9
almalinux 8|9
centos 9|10
@ -141,6 +143,7 @@ bash reinstall.sh anolis 7|8|23
kali
arch
gentoo
fnos
```
#### Optional Parameters
@ -195,7 +198,7 @@ bash reinstall.sh ubuntu --installer
- When deploy a Linux image, will **NOT** modify any contents of the image.
```bash
bash reinstall.sh dd --img https://example.com/xxx.xz
bash reinstall.sh dd --img "https://example.com/xxx.xz"
```
#### Optional parameters
@ -264,7 +267,7 @@ bash reinstall.sh netboot.xyz
```bash
bash reinstall.sh windows \
--image-name 'Windows 11 Enterprise LTSC 2024' \
--image-name "Windows 11 Enterprise LTSC 2024" \
--lang zh-cn
```
@ -321,8 +324,8 @@ zh-tw
```bash
bash reinstall.sh windows \
--image-name 'Windows 11 Enterprise LTSC 2024' \
--iso 'https://go.microsoft.com/fwlink/?linkid=2289029'
--image-name "Windows 11 Enterprise LTSC 2024" \
--iso "https://go.microsoft.com/fwlink/?linkid=2289029"
```
<details>
@ -357,13 +360,13 @@ bash reinstall.sh windows \
- `--rdp-port PORT` Change RDP port
- `--ssh-port PORT` Change SSH port (for log observation during installation)
- `--web-port PORT` Change Web port (for log observation during installation)
- `--add-driver-dir DIR` Adds an additional driver folder, specifying the folder where the .inf file is located.
- `--add-driver-dir DIR` Adds additional driver, specifying the folder where the .inf file is located.
- The driver must be downloaded locally first.
- This parameter can be set multiple times to add different driver folders.
- The script will copy the entire folder, so no other files should be placed inside the folder.
- `--hold 2` Allow SSH connections for modifying the disk content before rebooting into the official Windows installation program, with the disk mounted at `/os`.
#### The script will automatic download and install the following drivers as needed, without the need for manual addition
#### The following drivers will automatic download and install as needed, without the need for manual addition
- Virtio ([Virtio](https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/), [Alibaba Cloud](https://www.alibabacloud.com/help/ecs/user-guide/update-red-hat-virtio-drivers-of-windows-instances))
- XEN ([XEN](https://xenproject.org/resources/downloads/), [Citrix](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Upgrading_PV_drivers.html#win2008-citrix-upgrade), [AWS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/xen-drivers-overview.html))

View File

@ -15,7 +15,7 @@
## 亮点
- 一键安装 Linux支持 17 种常见发行版
- 一键安装 Linux支持 18 种常见发行版
- 一键安装 Windows使用官方 ISO 安装而非自制镜像,脚本会自动获取 ISO 链接、自动安装 Virtio 等驱动
- 支持任意方向重装,即 `Linux to Linux``Linux to Windows``Windows to Windows``Windows to Linux`
- 无需填写 IP 参数,自动识别动静态,支持 `/32``/128``网关不在子网范围内``纯 IPv6``双网卡` 等特殊网络
@ -31,7 +31,7 @@
目标系统的配置要求如下:
| 目标系统 | 版本 | 内存 | 硬盘 |
| 系统 | 版本 | 内存 | 硬盘 |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | --------- | ------------ |
| <img width="16" height="16" src="https://www.alpinelinux.org/alpine-logo.ico" /> Alpine | 3.18, 3.19, 3.20, 3.21 | 256 MB | 1 GB |
| <img width="16" height="16" src="https://www.debian.org/favicon.ico" /> Debian | 9, 10, 11, 12 | 256 MB | 1 ~ 1.5 GB ^ |
@ -47,6 +47,7 @@
| <img width="16" height="16" src="https://github.com/user-attachments/assets/99a542b6-6482-4086-addf-f192c06fef73" /> NixOS | 24.11 | 512 MB | 5 GB |
| <img width="16" height="16" src="https://archlinux.org/static/favicon.png" /> Arch | 滚动 | 512 MB | 5 GB |
| <img width="16" height="16" src="https://www.gentoo.org/assets/img/logo/gentoo-g.png" /> Gentoo | 滚动 | 512 MB | 5 GB |
| <img width="16" height="16" src="https://www.fnnas.com/favicon.ico" /> 飞牛 fnOS | 公测版 | 512 MB | 12 GB |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (DD) | 任何 | 512 MB | 取决于镜像 |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (ISO) | Vista, 7, 8.x (Server 2008 - 2012 R2) | 512 MB | 25 GB |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (ISO) | 10, 11 (Server 2016 - 2025) | 1 GB | 25 GB |
@ -111,8 +112,9 @@ certutil -urlcache -f -split https://gitlab.com/bin456789/reinstall/-/raw/main/r
**所有功能** 都可在 Linux / Windows 下运行
- Linux 下运行 `bash reinstall.sh`
- Windows 下运行 `.\reinstall.bat`
- Linux 下运行 `bash reinstall.sh ...`
- Windows 下先运行 `cmd`,再运行 `reinstall.bat ...`
- 如果参数中的链接包含特殊字符,要用 `""` 将链接包起来,不能用 `''`
### 功能 1: 安装 <img width="16" height="16" src="https://www.kernel.org/theme/images/logos/favicon.png" /> Linux
@ -127,7 +129,7 @@ certutil -urlcache -f -split https://gitlab.com/bin456789/reinstall/-/raw/main/r
bash reinstall.sh anolis 7|8|23
opencloudos 8|9|23
rocky 8|9
redhat 8|9 --img='http://xxx.com/xxx.qcow2'
redhat 8|9 --img="http://xxx.com/xxx.qcow2"
oracle 8|9
almalinux 8|9
centos 9|10
@ -141,6 +143,7 @@ bash reinstall.sh anolis 7|8|23
kali
arch
gentoo
fnos
```
#### 可选参数
@ -195,7 +198,7 @@ bash reinstall.sh ubuntu --installer
- DD Linux 镜像时,**不会**修改镜像的任何内容
```bash
bash reinstall.sh dd --img https://example.com/xxx.xz
bash reinstall.sh dd --img "https://example.com/xxx.xz"
```
#### 可选参数
@ -264,7 +267,7 @@ bash reinstall.sh netboot.xyz
```bash
bash reinstall.sh windows \
--image-name 'Windows 11 Enterprise LTSC 2024' \
--image-name "Windows 11 Enterprise LTSC 2024" \
--lang zh-cn
```
@ -321,8 +324,8 @@ zh-tw
```bash
bash reinstall.sh windows \
--image-name 'Windows 11 Enterprise LTSC 2024' \
--iso 'https://go.microsoft.com/fwlink/?linkid=2289029'
--image-name "Windows 11 Enterprise LTSC 2024" \
--iso "https://go.microsoft.com/fwlink/?linkid=2289029"
```
<details>
@ -357,13 +360,13 @@ bash reinstall.sh windows \
- `--rdp-port PORT` 更改 RDP 端口
- `--ssh-port PORT` 修改 SSH 端口(安装期间观察日志用)
- `--web-port PORT` 修改 Web 端口(安装期间观察日志用)
- `--add-driver-dir DIR` 添加额外驱动文件夹,填写 .inf 所在的文件夹
- `--add-driver-dir DIR` 添加额外驱动,填写 .inf 所在的文件夹
- 需先下载驱动到本地
- 可多次设置该参数以添加不同的驱动文件夹
- 脚本将复制整个文件夹,因此文件夹内不要放置其他文件
- `--hold 2` 在进入 Windows 官方安装程序之前,可以 SSH 登录修改硬盘内容,硬盘挂载在 `/os`
#### 脚本会自动按需下载安装以下驱动,无需手动添加
#### 以下驱动会自动按需下载安装,无需手动添加
- Virtio ([Virtio](https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/)、[阿里云](https://www.alibabacloud.com/help/ecs/user-guide/update-red-hat-virtio-drivers-of-windows-instances))
- XEN ([XEN](https://xenproject.org/resources/downloads/)、[Citrix](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Upgrading_PV_drivers.html#win2008-citrix-upgrade)、[AWS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/xen-drivers-overview.html))

View File

@ -204,13 +204,14 @@ test_by_wget() {
fi
# tcp 443 通了就算成功,不管 http 是不是 404
# grep -m1 快速返回
wget -T "$TEST_TIMEOUT" \
--bind-address="$src" \
--no-check-certificate \
--max-redirect 0 \
--tries 1 \
-O /dev/null \
"$url" 2>&1 | grep -iq connected
"$url" 2>&1 | grep -iq -m1 connected
}
test_by_nc() {

View File

@ -36,8 +36,8 @@ if not exist %tmp% (
rem 检查是否国内
if not exist geoip (
rem 部分地区 www.cloudflare.com 被墙
call :download http://dash.cloudflare.com/cdn-cgi/trace %~dp0geoip || goto :download_failed
rem www.cloudflare.com/dash.cloudflare.com 国内访问的是美国服务器,而且部分地区被墙
call :download http://www.visa.cn/cdn-cgi/trace %~dp0geoip || goto :download_failed
)
findstr /c:"loc=CN" geoip >nul
if not errorlevel 1 (

View File

@ -48,7 +48,7 @@ usage_and_exit() {
Usage: $reinstall_____ anolis 7|8|23
opencloudos 8|9|23
rocky 8|9
redhat 8|9 --img='http://xxx.com/xxx.qcow2'
redhat 8|9 --img="http://xxx.com/xxx.qcow2"
oracle 8|9
almalinux 8|9
centos 9|10
@ -62,9 +62,10 @@ Usage: $reinstall_____ anolis 7|8|23
kali
arch
gentoo
dd --img='http://xxx.com/yyy.zzz' (raw image stores in raw/vhd/tar/gz/xz/zst)
windows --image-name='windows xxx yyy' --lang=xx-yy
windows --image-name='windows xxx yyy' --iso='http://xxx.com/xxx.iso'
fnos
dd --img="http://xxx.com/yyy.zzz" (raw image stores in raw/vhd/tar/gz/xz/zst)
windows --image-name="windows xxx yyy" --lang=xx-yy
windows --image-name="windows xxx yyy" --iso="http://xxx.com/xxx.iso"
netboot.xyz
Options: [--ssh-port PORT]
@ -128,8 +129,8 @@ is_in_china() {
[ "$force_cn" = 1 ] && return 0
if [ -z "$_loc" ]; then
# 部分地区 www.cloudflare.com 被墙
_loc=$(curl -L http://dash.cloudflare.com/cdn-cgi/trace | grep '^loc=' | cut -d= -f2)
# www.cloudflare.com/dash.cloudflare.com 国内访问的是美国服务器,而且部分地区被墙
_loc=$(curl -L http://www.visa.cn/cdn-cgi/trace | grep '^loc=' | cut -d= -f2)
if [ -z "$_loc" ]; then
error_and_exit "Can not get location."
fi
@ -1358,6 +1359,9 @@ Continue?
# 注意 windows server 2008 r2 serverdatacenter 不用改
image_name=${image_name/windows server 2008 server/windows longhorn server}
if [[ "$iso" = magnet:* ]]; then
: # 不测试磁力链接
else
iso_filetype='iso raw'
iso_tested=false
@ -1379,11 +1383,10 @@ Continue?
test_url "$iso" "$iso_filetype"
fi
[ -n "$boot_wim" ] && test_url "$boot_wim" 'wim'
# 判断 iso 架构是否兼容
# https://gitlab.com/libosinfo/osinfo-db/-/tree/main/data/os/microsoft.com?ref_type=heads
if file -b "$tmp/img-test" | grep -q '_A64'; then
# uupdump linux 下合成的标签是 ARM64windows下合成的标签是 A64
if file -b "$tmp/img-test" | grep -Eq '_(A64|ARM64)'; then
iso_arch=arm64
else
iso_arch=x86_or_x64
@ -1401,6 +1404,9 @@ The current machine is $basearch, but it seems the ISO is for $iso_arch. Continu
exit
fi
fi
fi
[ -n "$boot_wim" ] && test_url "$boot_wim" 'wim'
eval "${step}_iso='$iso'"
eval "${step}_boot_wim='$boot_wim'"
@ -1449,6 +1455,30 @@ Continue with DD?
eval "${step}_img_type_warp='$img_type_warp'"
}
setos_fnos() {
if [ "$basearch" = aarch64 ]; then
error_and_exit "FNOS not supports ARM."
fi
# 系统盘大小
min=8
default=8
while true; do
IFS= read -r -p "Type System Partition Size in GB. Minimal $min GB. [$default]: " input
input=${input:-$default}
if ! { is_digit "$input" && [ "$input" -ge "$min" ]; }; then
error "Invalid Size. Please Try again."
else
eval "${step}_fnos_part_size=${input}G"
break
fi
done
iso=$(curl -L https://fnnas.com | grep -o 'https://[^"]*\.iso' | head -1)
test_url "$iso" 'iso'
eval "${step}_iso='$iso'"
}
setos_centos_almalinux_rocky_fedora() {
# el 10 需要 x86-64-v3
if [ "$basearch" = x86_64 ] &&
@ -1689,6 +1719,7 @@ verify_os_name() {
'kali' \
'arch' \
'gentoo' \
'fnos' \
'windows' \
'dd' \
'netboot.xyz'; do
@ -1947,7 +1978,7 @@ check_ram() {
alpine | debian | kali | dd) echo 256 ;;
arch | gentoo | nixos | windows) echo 512 ;;
redhat | centos | almalinux | rocky | fedora | oracle | ubuntu | anolis | opencloudos | openeuler) echo 1024 ;;
opensuse) echo -1 ;; # 没有安装模式
opensuse | fnos) echo -1 ;; # 没有安装模式
esac
)
@ -3696,15 +3727,14 @@ fi
# 密码
if ! is_netboot_xyz && [ -z "$password" ]; then
if is_use_dd; then
if is_use_dd || [ "$distro" = fnos ]; then
echo "
This password is only used for SSH access to view logs during the DD process.
This password is only used for SSH access to view logs during the installation.
Password of the image will NOT modify.
密码仅用于 DD 过程中通过 SSH 查看日志。
密码仅用于安装过程中通过 SSH 查看日志。
镜像的密码不会被修改。
"
fi
prompt_password
fi
@ -4135,7 +4165,7 @@ fi
info 'info'
echo "$distro $releasever"
if ! { is_netboot_xyz || is_use_dd; }; then
if ! { is_netboot_xyz || is_use_dd || [ "$distro" = fnos ]; }; then
if [ "$distro" = windows ]; then
username="administrator"
else
@ -4151,6 +4181,9 @@ elif is_alpine_live; then
echo 'Reboot to start Alpine Live OS.'
elif is_use_dd; then
echo 'Reboot to start DD.'
elif [ "$distro" = fnos ]; then
echo "Reboot to start the installation."
echo "After install, you need to config the system on http://SERVER_IP:5666 as soon as possible."
else
echo "Reboot to start the installation."
fi

444
trans.sh
View File

@ -84,12 +84,13 @@ wget() {
}
is_have_cmd() {
command -v "$1" >/dev/null
# command -v 包括脚本里面的方法
is_have_cmd_on_disk / "$1"
}
is_have_cmd_on_disk() {
os_dir=$1
cmd=$2
local os_dir=$1
local cmd=$2
for bin_dir in /bin /sbin /usr/bin /usr/sbin; do
if [ -f "$os_dir$bin_dir/$cmd" ]; then
@ -127,6 +128,18 @@ retry() {
done
}
get_url_type() {
if [[ "$1" = magnet:* ]]; then
echo bt
else
echo http
fi
}
is_magnet_link() {
[[ "$1" = magnet:* ]]
}
download() {
url=$1
path=$2
@ -138,26 +151,17 @@ download() {
# https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-o
# 构造 aria2 参数
# 没有指定文件名的情况
if [ -z "$path" ]; then
save=""
else
# 文件名是绝对路径
save=
# 文件夹
if [[ "$path" = '/*' ]]; then
save="-d / -o $path"
else
# 文件名是相对路径
save="-o $path"
save="$save -d /"
fi
fi
if ! is_have_cmd aria2c; then
apk add aria2
fi
# stdbuf 在 coreutils 包里面
if ! is_have_cmd stdbuf; then
apk add coreutils
# 文件名
if [ -n "$path" ]; then
case "$(get_url_type "$url")" in
http) save="$save -o $path" ;;
bt) save="$save -O 1=$path" ;;
esac
fi
# 阿里云源限速,而且检测 user-agent 禁止 axel/aria2 下载
@ -175,13 +179,18 @@ download() {
# fi
# --user-agent=Wget/1.21.1 \
# --retry-wait 5
echo "$url"
retry 5 5 stdbuf -oL -eL aria2c -x4 \
--allow-overwrite=true \
--summary-interval=0 \
--max-tries 1 \
$save "$url"
# 检测大小时已经下载了种子
if [ "$(get_url_type "$url")" = bt ]; then
torrent="$(get_torrent_path_by_magnet $url)"
if ! [ -f "$torrent" ]; then
download_torrent_by_magnet "$url" "$torrent"
fi
url=$torrent
fi
aria2c $save "$url"
}
update_part() {
@ -189,8 +198,9 @@ update_part() {
sync
# partprobe
# 有分区挂载中会报 Resource busy 错误
if is_have_cmd partprobe; then
partprobe /dev/$xda 2>/dev/null
partprobe /dev/$xda 2>/dev/null || true
fi
# partx
@ -413,7 +423,7 @@ EOF
umount_all() {
dirs="/mnt /os /iso /wim /installer /nbd /nbd-boot /nbd-efi /root /nix"
regex=$(echo "$dirs" | sed 's, ,|,g')
if mounts=$(mount | grep -Ew "$regex" | awk '{print $3}' | tac); then
if mounts=$(mount | grep -Ew "on $regex" | awk '{print $3}' | tac); then
for mount in $mounts; do
echo "umount $mount"
umount $mount
@ -1037,6 +1047,10 @@ EOF
done
}
newline_to_comma() {
tr '\n' ','
}
space_to_newline() {
sed 's/ /\n/g'
}
@ -1629,6 +1643,16 @@ EOF
show_nixos_config
}
add_fix_eth_name_systemd_service() {
os_dir=$1
# 无需执行 systemctl daemon-reload
# 因为 chroot 下执行会提示 Running in chroot, ignoring command 'daemon-reload'
download "$confhome/fix-eth-name.sh" "$os_dir/fix-eth-name.sh"
download "$confhome/fix-eth-name.service" "$os_dir/etc/systemd/system/fix-eth-name.service"
chroot "$os_dir" systemctl enable fix-eth-name
}
basic_init() {
os_dir=$1
@ -1678,13 +1702,8 @@ basic_init() {
# 下载 fix-eth-name.service
# 即使开了 net.ifnames=0 也需要
# 因为 alpine 和目标系统的网卡顺序可能不同
# 无需执行 systemctl daemon-reload
# 因为 chroot 下执行会提示 Running in chroot, ignoring command 'daemon-reload'
download "$confhome/fix-eth-name.sh" "$os_dir/fix-eth-name.sh"
download "$confhome/fix-eth-name.service" "$os_dir/etc/systemd/system/fix-eth-name.service"
chroot "$os_dir" systemctl enable fix-eth-name
# 因为 alpine live 和目标系统的网卡顺序可能不同
add_fix_eth_name_systemd_service $os_dir
}
install_arch_gentoo() {
@ -1936,12 +1955,8 @@ EOF
# 删除网卡名匹配
sed -i '/^Name=/d' $os_dir/etc/systemd/network/10-cloud-init-eth*.network
# 下载 fix-eth-name.service
# chroot 下执行 systemctl daemon-reload
# 会提示 Running in chroot, ignoring command 'daemon-reload'
download "$confhome/fix-eth-name.sh" "$os_dir/fix-eth-name.sh"
download "$confhome/fix-eth-name.service" "$os_dir/etc/systemd/system/fix-eth-name.service"
chroot "$os_dir" systemctl enable fix-eth-name
# 修正网卡名
add_fix_eth_name_systemd_service $os_dir
# arch gentoo 网络配置是用 alpine cloud-init 生成的
# cloud-init 版本够新,因此无需修复 onlink 网关
@ -1960,12 +1975,12 @@ EOF
# cmdline + 生成 grub.cfg
if [ -d $os_dir/etc/default/grub.d ]; then
file=$os_dir/etc/default/grub.d/cmdline.conf
file=$os_dir/etc/default/grub.d/tty.cfg
else
file=$os_dir/etc/default/grub
fi
ttys_cmdline=$(get_ttys console=)
echo GRUB_CMDLINE_LINUX=\"$ttys_cmdline\" >>$file
echo GRUB_CMDLINE_LINUX=\"\$GRUB_CMDLINE_LINUX $ttys_cmdline\" >>$file
chroot $os_dir grub-mkconfig -o /boot/grub/grub.cfg
# fstab
@ -1990,6 +2005,96 @@ get_http_file_size() {
tail -1 | awk '{print $2}' | grep .
}
get_url_hash() {
url=$1
echo "$url" | md5sum | awk '{print $1}'
}
aria2c() {
if ! is_have_cmd aria2c; then
apk add aria2
fi
# stdbuf 在 coreutils 包里面
if ! is_have_cmd stdbuf; then
apk add coreutils
fi
# 指定 bt 种子时没有链接,因此忽略错误
echo "$@" | grep -o '(http|https|magnet):[^ ]*' || true
# 下载 tracker
# 在 sub shell 里面无法保存变量,因此写入到文件
if echo "$@" | grep -Eq 'magnet:|\.torrent' && ! [ -f "/tmp/trackers" ]; then
# 独自一行下载,不然下载失败不会报错
# 里面有空行
# txt=$(wget -O- https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_best.txt | grep .)
# txt=$(wget -O- https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_all.txt | grep .)
txt=$(wget -O- https://cf.trackerslist.com/best.txt | grep .)
# sed 删除最后一个逗号
echo "$txt" | newline_to_comma | sed 's/,$//' >/tmp/trackers
fi
# --dht-entry-point=router.bittorrent.com:6881 \
# --dht-entry-point=dht.transmissionbt.com:6881 \
# --dht-entry-point=router.utorrent.com:6881 \
retry 5 5 stdbuf -oL -eL aria2c \
-x4 \
--seed-time=0 \
--allow-overwrite=true \
--summary-interval=0 \
--max-tries 1 \
--bt-tracker="$([ -f "/tmp/trackers" ] && cat /tmp/trackers)" \
"$@"
}
download_torrent_by_magnet() {
url=$1
dst=$2
url_hash=$(get_url_hash "$url")
mkdir -p /tmp/bt/$url_hash
# 不支持 -o bt.torrent 指定文件名
aria2c "$url" \
--bt-metadata-only=true \
--bt-save-metadata=true \
-d /tmp/bt/$url_hash
mv /tmp/bt/$url_hash/*.torrent "$dst"
rm -rf /tmp/bt/$url_hash
}
get_torrent_path_by_magnet() {
echo "/tmp/bt/$(get_url_hash "$1").torrent"
}
get_bt_file_size() {
url=$1
torrent="$(get_torrent_path_by_magnet $url)"
download_torrent_by_magnet "$url" "$torrent" >&2
# 列出第一个文件的大小
# idx|path/length
# ===+===========================================================================
# 1|./zh-cn_windows_11_consumer_editions_version_24h2_updated_jan_2025_x64_dvd_7a8e5a29.iso
# |6.1GiB (6,557,558,784)
aria2c --show-files=true "$torrent" |
grep -F -A1 ' 1|./' | tail -1 | grep -o '(.*)' | sed -E 's/[(),]//g' | grep .
}
get_link_file_size() {
if is_magnet_link "$1" >&2; then
get_bt_file_size "$1"
else
get_http_file_size "$1"
fi
}
pipe_extract() {
# alpine busybox 自带 gzip但官方版也许性能更好
case "$img_type_warp" in
@ -2073,7 +2178,7 @@ create_part() {
# xda*1 星号用于 nvme0n1p1 的字母 p
# shellcheck disable=SC2154
if [ "$distro" = windows ]; then
if ! size_bytes=$(get_http_file_size "$iso"); then
if ! size_bytes=$(get_link_file_size "$iso"); then
# 默认值最大的iso 23h2 假设 7g
size_bytes=$((7 * 1024 * 1024 * 1024))
fi
@ -2126,6 +2231,36 @@ create_part() {
mkfs.ntfs -f -F -L os /dev/$xda*1 #1 os
mkfs.ntfs -f -F -L installer /dev/$xda*2 #2 installer
fi
elif [ "$distro" = fnos ]; then
# 1. 官方安装器对系统盘大小的定义包含引导分区大小
# 2. 官方用的是 100M 而不是 100MiB
if is_efi; then
parted /dev/$xda -s -- \
mklabel gpt \
mkpart BOOT fat32 1MiB 100M \
mkpart SYSTEM ext4 100M ${fnos_part_size}iB \
mkpart TRIM ext4 ${fnos_part_size}iB 100% \
set 1 esp on
update_part
mkfs.fat /dev/$xda*1 #1 efi
echo #2 os 用目标系统的格式化工具
mkfs.ext4 -F /dev/$xda*3 #3 installer
else
# bios
# 官方安装器不支持 bios + >2t
parted /dev/$xda -s -- \
mklabel msdos \
mkpart primary 1MiB 100M \
mkpart primary 100M ${fnos_part_size}iB \
mkpart primary ${fnos_part_size}iB 100% \
set 2 boot on
update_part
echo #1 官方安装有这个分区
echo #2 os 用目标系统的格式化工具
mkfs.ext4 -F /dev/$xda*3 #3 installer
fi
elif is_use_cloud_image; then
installer_part_size="$(get_cloud_image_part_size)"
# 这几个系统不使用dd而是复制文件
@ -2280,9 +2415,24 @@ create_part() {
fi
}
umount_pseudo_fs() {
os_dir=$(realpath "$1")
dirs="/proc /sys /dev /run /sys/firmware/efi/efivars"
regex=$(echo "$dirs" | sed 's, ,|,g')
if mounts=$(mount | grep -Ew "on $os_dir($regex)" | awk '{print $3}' | tac); then
for mount in $mounts; do
echo "umount $mount"
umount $mount
done
fi
}
mount_pseudo_fs() {
os_dir=$1
mkdir -p $os_dir/proc/ $os_dir/sys/ $os_dir/dev/ $os_dir/run/
# https://wiki.archlinux.org/title/Chroot#Using_chroot
mount -t proc /proc $os_dir/proc/
mount -t sysfs /sys $os_dir/sys/
@ -2904,6 +3054,10 @@ EOF
! sh /can_use_cloud_kernel.sh "$xda" $(get_eths); then
kernel_package=$(echo "$kernel_package" | sed 's/-cloud//')
fi
# 如果镜像自带内核跟最佳内核是同一种且有更新
# 则 apt install 只会进行更新,不会将包设置成 manual
# 需要再运行 apt install 才会将包设置成 manual
chroot_apt_install $os_dir "$kernel_package"
chroot_apt_install $os_dir "$kernel_package"
# 使用 autoremove 删除非最佳内核
@ -3207,8 +3361,11 @@ modify_os_on_disk() {
if ls -d /os/*/ | grep -i '/windows/' 2>/dev/null; then
# 重新挂载为读写、忽略大小写
umount /os
apk add ntfs-3g
mount.lowntfs-3g /dev/$part /os -o ignore_case
mount -t ntfs3 -o nocase /dev/$part /os
# 有休眠文件时无法挂载成读写,提醒用户并退出脚本
if mount | grep ' /os ' | grep -wq ro; then
error_and_exit "Can't mount windows partition /dev/$part as rw."
fi
modify_windows /os
return
fi
@ -3609,6 +3766,120 @@ EOF
fi
}
install_fnos() {
info "Install fnos"
os_dir=/os
# 官方安装调用流程
# /etc/init.d/run_install.sh > trim-install > trim-grub
# 挂载 installer iso
mkdir -p /installer /iso
mount /dev/$xda*3 /installer
download "$iso" /installer/fnos.iso
mount /installer/fnos.iso /iso
# 解压 initrd
apk add cpio
initrd_dir=/installer/initrd_dir
mkdir -p $initrd_dir
(
cd $initrd_dir
zcat /iso/install.amd/initrd.gz | cpio -idm
)
apk del cpio
# 格式化系统盘
mount_pseudo_fs $initrd_dir
chroot $initrd_dir mkfs.ext4 /dev/$xda*2
umount_pseudo_fs $initrd_dir
# 获取挂载参数
fstab_line_os=$(strings $initrd_dir/trim-install | grep -m1 '^UUID=%s / ')
fstab_line_efi=$(strings $initrd_dir/trim-install | grep -m1 '^UUID=%s /boot/efi ')
fstab_line_swapfile=$(strings $initrd_dir/trim-install | grep -m1 '^/swapfile none swap ')
# 挂载 /os
mkdir -p /os
mount /dev/$xda*2 /os
# 复制系统
info "Extract fnos"
apk add tar gzip pv
pv -f /iso/trimfs.tgz | tar zx -C /os --numeric-owner
apk del tar gzip pv
# 挂载 /os/boot/efi
if is_efi; then
mkdir -p /os/boot/efi
mount -o "$(echo "$fstab_line_efi" | awk '{print $4}')" /dev/$xda*1 /os/boot/efi
fi
# 挂载 proc sys dev
mount_pseudo_fs /os
# 卸载 iso installer
umount /iso
umount /installer
# 删除 installer 分区
apk add parted
parted -s /dev/$xda rm 3
apk del parted
update_part
# 更新 initrd
# chroot $os_dir update-initramfs -u
# 删除自带的 root 密码
# chroot $os_dir passwd -d root
# ssh root 登录,测试用
if false; then
echo "root:$(get_password_linux_sha512)" | chroot $os_dir chpasswd -e
allow_root_password_login $os_dir
chroot $os_dir systemctl enable ssh
fi
# grub
if is_efi; then
chroot $os_dir grub-install --efi-directory=/boot/efi
chroot $os_dir grub-install --efi-directory=/boot/efi --removable
else
chroot $os_dir grub-install /dev/$xda
fi
# grub tty
ttys_cmdline=$(get_ttys console=)
echo GRUB_CMDLINE_LINUX=\"\$GRUB_CMDLINE_LINUX $ttys_cmdline\" \
>>$os_dir/etc/default/grub.d/tty.cfg
chroot $os_dir update-grub
# fstab
{
# /
uuid=$(lsblk /dev/$xda*2 -no UUID)
echo "$fstab_line_os" | sed "s/%s/$uuid/"
# 官方安装器即使 swapfile 设为 0 也会有这行
echo "$fstab_line_swapfile" | sed "s/%s/$uuid/"
# /boot/efi
if is_efi; then
uuid=$(lsblk /dev/$xda*1 -no UUID)
echo "$fstab_line_efi" | sed "s/%s/$uuid/"
fi
} >$os_dir/etc/fstab
# 网卡配置
create_cloud_init_network_config /net.cfg
create_network_manager_config /net.cfg $os_dir
rm /net.cfg
# 修正网卡名
add_fix_eth_name_systemd_service $os_dir
}
install_qcow_by_copy() {
info "Install qcow2 by copy"
@ -3909,6 +4180,10 @@ EOF
# 安装最佳内核
flavor=$(get_ubuntu_kernel_flavor)
echo "Use kernel flavor: $flavor"
# 如果镜像自带内核跟最佳内核是同一种且有更新
# 则 apt install 只会进行更新,不会将包设置成 manual
# 需要再运行 apt install 才会将包设置成 manual
chroot_apt_install $os_dir "linux-image-$flavor"
chroot_apt_install $os_dir "linux-image-$flavor"
# 使用 autoremove 删除多余内核
@ -4454,7 +4729,7 @@ mount_part_for_iso_installer() {
info "Mount part for iso installer"
if [ "$distro" = windows ]; then
mount_args="-t ntfs3"
mount_args="-t ntfs3 -o nocase"
else
mount_args=
fi
@ -4725,32 +5000,53 @@ install_windows() {
get_image_prop "$iso_install_wim" "$image_name" "$1"
}
# PRODUCTTYPE:
# - WinNT (普通 windows)
# - ServerNT (windows server)
# 多会话的信息来自注册表,因为没有官方 iso
# INSTALLATIONTYPE:
# Installation Type:
# - Client (普通 windows)
# - Server (windows server 带桌面体验)
# - Server Core (windows server 不带桌面体验)
# - Embedded (WES7 / Thin PC)
# - Client (windows 10/11 enterprise 多会话)
# Product Type:
# https://cloud.tencent.com/developer/article/2465206
# https://learn.microsoft.com/en-us/azure/virtual-desktop/windows-multisession-faq#why-does-my-application-report-windows-enterprise-multi-session-as-a-server-operating-system
# - WinNT (普通 windows)
# - ServerNT (windows server 带桌面体验)
# - ServerNT (windows server 不带桌面体验)
# - WinNT (WES7 / Thin PC)
# - ServerNT (windows 10/11 enterprise 多会话)
# Product Suite:
# https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/exinit/productsuite.htm
# - Terminal Server (普通 windows)
# - Enterprise (windows server 带桌面体验)
# - Enterprise (windows server 不带桌面体验)
# - Terminal Server (WES7 / Thin PC)
# - ? (windows 10/11 enterprise 多会话)
# 用内核版本号筛选驱动
# 使得可以安装 Hyper-V Server / Azure Stack HCI 等 Windows Server 变种
nt_ver=$(get_selected_image_prop "Major Version").$(get_selected_image_prop "Minor Version")
build_ver=$(get_selected_image_prop "Build")
product_type=$(get_selected_image_prop "Product Type")
product_suite=$(get_selected_image_prop "Product Suite")
product_ver=$(
case $product_type in
WinNT) get_client_name_by_build_ver "$build_ver" ;;
ServerNT) get_server_name_by_build_ver "$build_ver" ;;
case "$product_suite" in
'Terminal Server')
windows_type=client
product_ver=$(get_client_name_by_build_ver "$build_ver")
;;
*)
windows_type=server
product_ver=$(get_server_name_by_build_ver "$build_ver")
;;
esac
)
info "Selected image info"
echo "Image Name: $image_name"
echo "Product Version: $product_ver"
echo "Product Type: $product_type"
echo "Windows Type: $windows_type"
echo "NT Version: $nt_ver"
echo "Build Version: $build_ver"
echo
@ -5040,9 +5336,9 @@ install_windows() {
case "$(echo "$product_ver" | to_lower)" in
'vista') echo 2k8 ;; # 没有 vista 文件夹
*)
case "$product_type" in
WinNT) echo "w$product_ver" ;;
ServerNT) echo "$product_ver" | sed -E -e 's/ //' -e 's/^200?/2k/' -e 's/r2/R2/' ;;
case "$windows_type" in
client) echo "w$product_ver" ;;
server) echo "$product_ver" | sed -E -e 's/ //' -e 's/^200?/2k/' -e 's/r2/R2/' ;;
esac
;;
esac
@ -5127,8 +5423,6 @@ install_windows() {
mv -v "$file" "$new_file"
done
)
# 虽然 vista/7 气球驱动有问题,但 msi 里面没有 vista/7 驱动
# 因此不用额外处理
cp_drivers $drv/virtio
fi
}
@ -5340,9 +5634,15 @@ install_windows() {
fi
fi
mkdir -p /wim
# 挂载 install.wim检查是否有 sac 组件
wimmount "$install_wim" "$image_name" /wim/
[ -f /wim/Windows/System32/sacsess.exe ] && has_sac=true || has_sac=false
wimunmount /wim/
# 挂载 boot.wim
info "mount boot.wim"
mkdir -p /wim
wimmountrw /os/boot.wim "$boot_index" /wim/
cp_drivers() {
@ -5394,8 +5694,9 @@ install_windows() {
mv /wim/setup.exe /wim/setup.exe.disabled
# 如果有重复的 Windows/System32 文件夹,会提示找不到 winload.exe 无法引导
# win7 win10 是 Windows/System32
# win2016 是 windows/system32
# win7 win10 boot.wim 是 Windows/System32install.wim 是 Windows/System32
# win2016 boot.wim 是 windows/system32install.wim 是 Windows/System32
# wimmount 无法挂载成忽略大小写
# shellcheck disable=SC2010
system32_dir=$(ls -d /wim/*/*32 | grep -i windows/system32)
download $confhome/windows-setup.bat $system32_dir/startnet.cmd
@ -5407,6 +5708,11 @@ install_windows() {
sed -i 's/ForceOldSetup=0/ForceOldSetup=1/i' $system32_dir/startnet.cmd
fi
# 有 SAC 组件时,启用 EMS
if $has_sac; then
sed -i 's/EnableEMS=0/EnableEMS=1/i' $system32_dir/startnet.cmd
fi
# Windows Thin PC 有 Windows\System32\winpeshl.ini
# [LaunchApps]
# %SYSTEMDRIVE%\windows\system32\drvload.exe, %SYSTEMDRIVE%\windows\inf\sdbus.inf
@ -5789,6 +6095,10 @@ trans() {
create_part
install_nixos
;;
fnos)
create_part
install_fnos
;;
*)
create_part
mount_part_for_iso_installer

View File

@ -49,9 +49,9 @@ echo list vol | diskpart | find "efi" && (
)
rem 获取 ProductType
for /f "tokens=3" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions" /v ProductType') do (
set "ProductType=%%a"
)
rem for /f "tokens=3" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions" /v ProductType') do (
rem set "ProductType=%%a"
rem )
rem 获取 BuildNumber
for /f "tokens=3" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v CurrentBuildNumber') do (
@ -155,6 +155,7 @@ for %%a in (RAM TPM SecureBoot) do (
rem 设置
set ForceOldSetup=0
set EnableUnattended=1
set EnableEMS=0
rem 运行 ramdisk X:\setup.exe 的话
rem vista 会找不到安装源
@ -190,9 +191,10 @@ if %BuildNumber% GEQ 26040 if "%ForceOldSetup%"=="0" (
set ResizeRecoveryPartition=/ResizeRecoveryPartition Disable
)
rem 为 windows server 打开 EMS
rem 普通 windows 没有自带 EMS 组件,暂不处理
if "%ProductType%"=="ServerNT" (
rem 为 windows server 打开 EMS/SAC
rem 普通 windows 没有自带 SAC 组件,暂不处理
rem 现在通过 trans.sh 准确检测系统是否有 SAC 组件,有则修改 EnableEMS 变量打开 EMS
if "%EnableEMS%"=="1" (
rem set EMS=/EMSPort:UseBIOSSettings /EMSBaudRate:115200
set EMS=/EMSPort:COM1 /EMSBaudRate:115200
)