Files
cellular-proxy/scripts/fetch-binaries.sh
T
Hermes 91939c7cc2 feat: UI/CLI 配置代理账密;armv7 仅保留整包
- 面板可设置 7890 账号密码(管理 API :9091)
- cpxy auth --user/--pass/--clear/--show
- Release armv7 整包已验证,已删除分片资产
2026-07-21 12:29:57 +00:00

257 lines
7.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 仅下载/安装 sing-box(轻量核心)
# 优先级:local → 系统已有 → Gitea Release(整包/分片)→ GitHub 代理 → 直连 GitHub
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=lib.sh
source "$ROOT_DIR/scripts/lib.sh"
load_config
need_root
ensure_dirs
mkdir -p /var/lib/cellular-proxy
ARCH="$(arch_go)"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
GITHUB_PROXY="${GITHUB_PROXY:-https://git.86482425.xyz}"
GITEA_BASE="${GITEA_BASE:-https://gitea.chickliu.fun}"
GITEA_OWNER="${GITEA_OWNER:-Hermes}"
GITEA_REPO="${GITEA_REPO:-cellular-proxy}"
SING_BOX_RELEASE_TAG="${SING_BOX_RELEASE_TAG:-bin-v${SING_BOX_VERSION}}"
# gitea | github | auto | local | release
SING_BOX_SOURCE="${SING_BOX_SOURCE:-auto}"
github_url() {
local raw="$1"
local proxy="${GITHUB_PROXY:-}"
if [[ -z "$proxy" ]]; then
echo "$raw"
return
fi
proxy="${proxy%/}"
case "$raw" in
"${proxy}"/*) echo "$raw"; return ;;
esac
echo "${proxy}/${raw}"
}
download() {
local url="$1" dest="$2"
info "下载: $url"
if command -v curl >/dev/null 2>&1; then
curl -fL --retry 3 --connect-timeout 20 --max-time 300 -o "$dest" "$url"
elif command -v wget >/dev/null 2>&1; then
wget -O "$dest" "$url"
else
die "需要 curl 或 wget"
fi
}
# 静默探测 URL 是否可下(不写盘)
url_ok() {
local url="$1"
if command -v curl >/dev/null 2>&1; then
curl -fsSIL --connect-timeout 8 --max-time 20 -o /dev/null "$url" 2>/dev/null
else
return 1
fi
}
download_github() {
local raw="$1" dest="$2"
local proxied
proxied="$(github_url "$raw")"
if [[ "$proxied" != "$raw" ]]; then
info "经 GitHub 代理下载: $proxied"
if download "$proxied" "$dest"; then
return 0
fi
warn "代理下载失败,尝试直连 GitHub: $raw"
fi
download "$raw" "$dest"
}
install_from_tarball() {
local tgz="$1" ver="$2" arch="$3"
local name="sing-box-${ver}-linux-${arch}"
tar -xzf "$tgz" -C "$TMP"
if [[ -x "$TMP/${name}/sing-box" ]]; then
install -m 0755 "$TMP/${name}/sing-box" "$INSTALL_DIR/bin/sing-box"
elif [[ -x "$TMP/sing-box" ]]; then
install -m 0755 "$TMP/sing-box" "$INSTALL_DIR/bin/sing-box"
else
local found
found="$(find "$TMP" -type f -name sing-box 2>/dev/null | head -1)"
[[ -n "$found" && -x "$found" ]] || die "压缩包内未找到 sing-box 可执行文件"
install -m 0755 "$found" "$INSTALL_DIR/bin/sing-box"
fi
}
gitea_asset_url() {
local fname="$1"
echo "${GITEA_BASE%/}/${GITEA_OWNER}/${GITEA_REPO}/releases/download/${SING_BOX_RELEASE_TAG}/${fname}"
}
# 从 Gitea 拉整包 tar.gz
try_download_gitea_whole() {
local ver="$1" arch="$2" dest="$3"
local name url
name="sing-box-${ver}-linux-${arch}.tar.gz"
url="$(gitea_asset_url "$name")"
info "尝试 Gitea 预置整包: $url"
if download "$url" "$dest"; then
return 0
fi
return 1
}
# 代理 504 时可能只提供分片:name.tar.gz.part-00.. + name.tar.gz.SHA256SUMS
try_download_gitea_parts() {
local ver="$1" arch="$2" dest="$3"
local base name sums_url part_url part_dir i max
name="sing-box-${ver}-linux-${arch}.tar.gz"
base="${GITEA_BASE%/}/${GITEA_OWNER}/${GITEA_REPO}/releases/download/${SING_BOX_RELEASE_TAG}"
sums_url="${base}/${name}.SHA256SUMS"
# 兼容旧名 SHA256SUMS(仅 armv7 曾用)
part_dir="$TMP/parts_${arch}"
mkdir -p "$part_dir"
if download "$sums_url" "$part_dir/SHA256SUMS" 2>/dev/null; then
info "发现分片清单: $sums_url"
elif [[ "$arch" == "armv7" ]] && download "$(gitea_asset_url SHA256SUMS)" "$part_dir/SHA256SUMS" 2>/dev/null; then
info "使用兼容清单 SHA256SUMS"
else
return 1
fi
# 从清单提取 part 文件名(去掉路径前缀)
mapfile -t parts < <(awk '{print $2}' "$part_dir/SHA256SUMS" | sed 's|^\./||' | grep -E '\.part-[0-9]+$' || true)
if [[ ${#parts[@]} -eq 0 ]]; then
# 无清单文件名时按 part-00..99 探测
parts=()
for i in $(seq -w 0 99); do
part_url="${base}/${name}.part-${i}"
if url_ok "$part_url"; then
parts+=("${name}.part-${i}")
else
[[ ${#parts[@]} -gt 0 ]] && break
fi
done
fi
[[ ${#parts[@]} -gt 0 ]] || return 1
info "Gitea 分片下载 ${#parts[@]} 片 → 合并 $name"
: >"$dest"
for p in "${parts[@]}"; do
p="${p#./}"
# 若清单里只有 basename part-xx,补全前缀
case "$p" in
*.part-*) ;;
*) p="${name}.part-${p##*-}" ;;
esac
# 清单可能是 relative part name only like sing-box-...part-00
if [[ "$p" != *"/"* && "$p" != ${name}.part-* && "$p" == *.part-* ]]; then
:
fi
part_url="${base}/${p}"
if ! download "$part_url" "$part_dir/$p"; then
# 尝试无前缀名
local bn
bn="$(basename "$p")"
part_url="${base}/${bn}"
download "$part_url" "$part_dir/$bn" || return 1
p="$bn"
fi
cat "$part_dir/$p" >>"$dest"
done
# 可选校验
if command -v sha256sum >/dev/null 2>&1; then
(
cd "$part_dir"
# 规范化清单路径
sed 's| \./| |; s|^\([a-f0-9]*\) \./|\1 |' SHA256SUMS > SHA256SUMS.norm || cp SHA256SUMS SHA256SUMS.norm
if sha256sum -c SHA256SUMS.norm --status 2>/dev/null; then
info "分片 SHA256 校验通过"
else
warn "分片 SHA256 校验跳过/未严格通过(已合并,继续)"
fi
) || true
fi
# 快速完整性:tar 列表
tar -tzf "$dest" >/dev/null
return 0
}
try_download_gitea() {
local ver="$1" arch="$2" dest="$3"
if try_download_gitea_whole "$ver" "$arch" "$dest"; then
return 0
fi
warn "Gitea 整包不可用,尝试分片合并(大文件/代理 504 兜底)"
if try_download_gitea_parts "$ver" "$arch" "$dest"; then
return 0
fi
return 1
}
try_download_github_release() {
local ver="$1" arch="$2" dest="$3"
local name raw_url
name="sing-box-${ver}-linux-${arch}"
raw_url="https://github.com/SagerNet/sing-box/releases/download/v${ver}/${name}.tar.gz"
download_github "$raw_url" "$dest"
}
if [[ "$SING_BOX_SOURCE" == "local" ]]; then
[[ -n "$SING_BOX_BIN" && -x "$SING_BOX_BIN" ]] || die "SING_BOX_SOURCE=local 但 SING_BOX_BIN 无效"
install -m 0755 "$SING_BOX_BIN" "$INSTALL_DIR/bin/sing-box"
info "已安装本地 sing-box"
elif command -v sing-box >/dev/null 2>&1 && [[ -z "${FORCE_DOWNLOAD:-}" && "$SING_BOX_SOURCE" != "gitea" && "$SING_BOX_SOURCE" != "github" ]]; then
install -m 0755 "$(command -v sing-box)" "$INSTALL_DIR/bin/sing-box"
info "复用系统 sing-box: $(command -v sing-box)"
else
ver="$SING_BOX_VERSION"
tgz="$TMP/sb.tgz"
ok=0
case "$SING_BOX_SOURCE" in
gitea)
try_download_gitea "$ver" "$ARCH" "$tgz" || die "Gitea 预置包下载失败(tag=$SING_BOX_RELEASE_TAG arch=$ARCH"
ok=1
;;
github|release)
try_download_github_release "$ver" "$ARCH" "$tgz"
ok=1
;;
auto|*)
if try_download_gitea "$ver" "$ARCH" "$tgz"; then
ok=1
info "已从 Gitea Release 获取 sing-box"
else
warn "Gitea 预置包不可用,回退 GitHub(经 ${GITHUB_PROXY:-直连}"
try_download_github_release "$ver" "$ARCH" "$tgz"
ok=1
fi
;;
esac
[[ "$ok" -eq 1 ]] || die "无法下载 sing-box"
install_from_tarball "$tgz" "$ver" "$ARCH"
info "已安装 sing-box v${ver} (${ARCH})"
"$INSTALL_DIR/bin/sing-box" version 2>/dev/null | head -3 || true
fi
# 安装中文静态 UI
mkdir -p "$INSTALL_DIR/ui"
if [[ -f "$ROOT_DIR/ui/index.html" ]]; then
cp -a "$ROOT_DIR/ui/." "$INSTALL_DIR/ui/"
info "已安装内置中文面板 -> $INSTALL_DIR/ui"
else
warn "未找到 ui/index.html"
fi
info "二进制就绪:"
ls -la "$INSTALL_DIR/bin"
du -sh "$INSTALL_DIR/bin" "$INSTALL_DIR/ui" 2>/dev/null || true