Files
NexusGate/scripts/agent-singbox.sh
T
2026-10-20 12:33:22 +08:00

115 lines
5.6 KiB
Bash
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
set -Eeuo pipefail
[[ "${EUID}" -eq 0 ]] || { printf '请使用 root 运行\n' >&2; exit 1; }
[[ "${1:-install}" == install ]] || { printf '用法:ng-agent engine install\n' >&2; exit 1; }
# Build a version pinned to the configuration model tested by NexusGate.
# Official builds do not guarantee the optional V2Ray statistics API.
version='v1.13.21'
target='/usr/local/bin/nexusgate-sing-box'
stats_target='/usr/local/bin/nexusgate-sing-box-stats'
if [[ -x "$target" && -x "$stats_target" && "${2:-}" != '--force' ]]; then
printf 'sing-box 已安装:%s(如需重装,运行 ng-agent-singbox install --force)\n' "$target"
exit 0
fi
# 优先从 GitHub Release 下载预编译二进制,免去现场编译
# Release tag: sing-box-v1.13.21,需上传 nexusgate-sing-box-linux-<arch> 和 nexusgate-sing-box-stats-linux-<arch>
try_prebuilt() {
local arch dl_arch release_tag base_url tmp_bin tmp_stats
case "$(uname -m)" in
x86_64|amd64) dl_arch=amd64 ;;
aarch64|arm64) dl_arch=arm64 ;;
*) return 1 ;;
esac
release_tag="${NG_SINGBOX_RELEASE:-sing-box-v1.13.21}"
base_url="https://github.com/aaaamoooo/NexusGate/releases/download/${release_tag}"
tmp_bin="$(mktemp /tmp/nexusgate-singbox-bin.XXXXXX)"
tmp_stats="$(mktemp /tmp/nexusgate-singbox-stats.XXXXXX)"
trap 'rm -f -- "$tmp_bin" "$tmp_stats"' RETURN
printf '尝试从 GitHub Release 下载预编译 sing-box...\n'
if curl -fL --retry 2 --connect-timeout 15 -o "$tmp_bin" "${base_url}/nexusgate-sing-box-linux-${dl_arch}" 2>/dev/null && \
curl -fL --retry 2 --connect-timeout 15 -o "$tmp_stats" "${base_url}/nexusgate-sing-box-stats-linux-${dl_arch}" 2>/dev/null; then
chmod +x "$tmp_bin" "$tmp_stats"
# 简单验证二进制可执行
if "$tmp_bin" version >/dev/null 2>&1; then
install -m 0755 "$tmp_bin" "${target}.next"
install -m 0755 "$tmp_stats" "${stats_target}.next"
mv -f "${target}.next" "$target"
mv -f "${stats_target}.next" "$stats_target"
printf 'sing-box 预编译版安装完成:%s\n' "$target"
return 0
fi
fi
printf '预编译包下载失败,回退到源码编译\n'
return 1
}
if [[ "${NG_SINGBOX_NO_PREBUILT:-}" != "1" ]]; then
try_prebuilt && exit 0
fi
build_dir="$(mktemp -d /tmp/nexusgate-singbox.XXXXXX)"
trap 'rm -rf -- "$build_dir"' EXIT
# Go's module and build caches can occupy hundreds of MB indefinitely on a
# 1 GB relay. Keep them temporary, but OUTSIDE the stats helper's module root:
# `go mod tidy` recursively scans that root and must not scan caches/toolchains.
export GOMODCACHE="$build_dir/gomod" GOCACHE="$build_dir/gocache"
stats_source_dir="$build_dir/stats-source"
install -d -m 0700 "$stats_source_dir"
go_version="$(go version 2>/dev/null || true)"
go_major=0 go_minor=0
if [[ "$go_version" =~ go([0-9]+)\.([0-9]+) ]]; then
go_major="${BASH_REMATCH[1]}"
go_minor="${BASH_REMATCH[2]}"
fi
if (( go_major < 1 || (go_major == 1 && go_minor < 23) )); then
case "$(uname -m)" in
x86_64|amd64) go_arch=amd64; go_sha=49bbb517cfa9eee677e1e7897f7cf9cfdbcf49e05f61984a2789136de359f9bd ;;
aarch64|arm64) go_arch=arm64; go_sha=faec7f7f8ae53fda0f3d408f52182d942cc89ef5b7d3d9f23ff117437d4b2d2f ;;
armv7l) go_arch=armv6l; go_sha=6c7832c7dcd8fb6d4eb308f672a725393403c74ee7be1aeccd8a443015df99de ;;
*) printf '此架构无法自动构建 sing-box:%s\n' "$(uname -m)" >&2; exit 1 ;;
esac
printf '系统 Go 版本过旧;下载已校验的 Go 1.23.1 构建工具链...\n'
curl -fL --retry 3 "https://go.dev/dl/go1.23.1.linux-${go_arch}.tar.gz" -o "$build_dir/go.tar.gz"
printf '%s %s\n' "$go_sha" "$build_dir/go.tar.gz" | sha256sum -c -
tar -C "$build_dir" -xzf "$build_dir/go.tar.gz"
export PATH="$build_dir/go/bin:$PATH"
fi
printf '构建 sing-box %s(启用 V2Ray 统计 API,首次需下载 Go 依赖)...\n' "$version"
GOBIN="$build_dir" GOTOOLCHAIN=auto GOMAXPROCS=1 go install -trimpath -ldflags='-s -w' -p 1 -tags with_v2ray_api "github.com/sagernet/sing-box/cmd/sing-box@${version}"
[[ -s "$build_dir/sing-box" ]] || { printf 'sing-box 构建失败\n' >&2; exit 1; }
repo="${NG_REPO:-a2899882/NexusGate}"
branch="${NG_BRANCH:-main}"
if [[ -n "${NG_STATS_SOURCE:-}" ]]; then
install -m 0600 "$NG_STATS_SOURCE" "$stats_source_dir/stats-query.go"
else
curl -fL --retry 3 "https://raw.githubusercontent.com/${repo}/${branch}/agent/stats-query.go" -o "$stats_source_dir/stats-query.go"
fi
( cd "$stats_source_dir"
GOTOOLCHAIN=auto go mod init nexusgate/statsquery
GOTOOLCHAIN=auto go get "github.com/sagernet/sing-box@${version}"
GOTOOLCHAIN=auto GOMAXPROCS=1 go mod tidy
GOTOOLCHAIN=auto GOMAXPROCS=1 go build -trimpath -ldflags='-s -w' -p 1 -o "$build_dir/stats-query" stats-query.go
)
[[ -s "$build_dir/stats-query" ]] || { printf 'sing-box 统计组件构建失败\n' >&2; exit 1; }
# A configuration with a statistics endpoint must pass validation before replacing a working binary.
cat > "$build_dir/check.json" <<'EOF'
{"log":{"level":"warn"},"inbounds":[],"outbounds":[{"type":"direct","tag":"direct"}],"experimental":{"v2ray_api":{"listen":"127.0.0.1:10086","stats":{"enabled":true,"inbounds":[]}}}}
EOF
"$build_dir/sing-box" check -c "$build_dir/check.json"
install -m 0755 "$build_dir/sing-box" "$target.next"
install -m 0755 "$build_dir/stats-query" "$stats_target.next"
mv -f -- "$target.next" "$target"
mv -f -- "$stats_target.next" "$stats_target"
printf 'sing-box 统计版已安装:%s\n' "$target"
if [[ -f /etc/nexusgate/sing-box/config.json ]]; then
if command -v systemctl >/dev/null && [[ -d /run/systemd/system ]]; then
systemctl restart nexusgate-sing-box.service
elif command -v rc-service >/dev/null; then
rc-service nexusgate-sing-box restart
fi
fi