windows: 支持磁力链接下载 iso

fixes #268
This commit is contained in:
bin456789
2025-02-21 00:30:33 +08:00
parent 8e8bf610dc
commit 6263f994af
2 changed files with 173 additions and 65 deletions

View File

@ -1358,6 +1358,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 +1382,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 +1403,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'"

159
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() {
@ -1037,6 +1046,10 @@ EOF
done
}
newline_to_comma() {
tr '\n' ','
}
space_to_newline() {
sed 's/ /\n/g'
}
@ -1990,6 +2003,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 +2176,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