Files
NexusGate/scripts/agent-update.sh
T
aaaamoooo f4ef3d96a6
CI / test (push) Canceled after 0s
CI / anytls-smoke (push) Canceled after 0s
chore: migrate self-distribution links from GitHub to self-hosted Gitea
GitHub accounts suspended; all first-party distribution now served from
git.881218.xyz/rogue/NexusGate (Gitea):
- raw:  /rogue/NexusGate/raw/branch/<branch>/<path>
- release assets and source archives under the same repo path
- scripts gain a GIT_BASE variable built from NG_REPO (default
  rogue/NexusGate); NG_REPO/NG_BRANCH/--repo/--branch semantics unchanged
- panel enrollment/uninstall commands in public/app.js point at Gitea raw
- install.sh/nexusgate.sh/agent-singbox.sh stats source previously
  defaulted to the upstream repo (a2899882); defaults now this repo
Upstream dependency references (sagernet/sing-box Go module) untouched.
2026-10-20 11:05:55 +00:00

154 lines
6.8 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
set -Eeuo pipefail
REPO="${NG_REPO:-rogue/NexusGate}"
BRANCH="${NG_BRANCH:-main}"
# 自建 Gitea 分发基址(raw / release 均由此拼装)
GIT_BASE="https://git.881218.xyz/${REPO}"
# Go agent 二进制所在的 Gitea Release tag(与 agent-install.sh 保持一致)
AGENT_RELEASE="${NG_AGENT_RELEASE:-agent-v0.6.8}"
die() { printf '错误:%s\n' "$*" >&2; exit 1; }
info() { printf '\033[1;36m[NexusGate Agent]\033[0m %s\n' "$*"; }
[[ "${EUID}" -eq 0 ]] || die "请使用 root 运行"
[[ -f /etc/nexusgate/agent.env ]] || die "未检测到已安装的 NexusGate Agent"
command -v curl >/dev/null || die "缺少 curl"
tmp_dir="$(mktemp -d /tmp/nexusgate-agent-update.XXXXXX)"
trap 'rm -rf -- "$tmp_dir"' EXIT
# 按已安装的程序判断当前实现:Go 二进制优先,其次是旧版 Node agent.js
if [[ -x /opt/nexusgate-agent/nexusgate-agent ]]; then
CURRENT_IMPL="go"
elif [[ -f /opt/nexusgate-agent/agent.js ]]; then
CURRENT_IMPL="node"
else
die "未找到 Agent 程序(/opt/nexusgate-agent/nexusgate-agent 或 agent.js)"
fi
# 目标实现:更新默认迁移到 Go;显式 NG_AGENT_IMPL=node 时保留 Node
TARGET_IMPL="go"
[[ "${NG_AGENT_IMPL:-}" == "node" ]] && TARGET_IMPL="node"
info "当前 Agent 实现:${CURRENT_IMPL};更新目标:${TARGET_IMPL}"
raw_fetch() {
curl -fL --retry 3 "${GIT_BASE}/raw/branch/${BRANCH}/$1" -o "$2"
}
agent_arch() {
case "$(uname -m)" in
x86_64|amd64) printf 'amd64' ;;
aarch64|arm64) printf 'arm64' ;;
*) return 1 ;;
esac
}
# 下载 Go agent 二进制到 $1(NG_LOCAL_SRC 时从 agent-go/ 取已构建产物)
fetch_agent_binary() {
local arch out="$1"
arch="$(agent_arch)" || die "不支持的架构:$(uname -m)"
if [[ -n "${NG_LOCAL_SRC:-}" && -f "${NG_LOCAL_SRC}/agent-go/nexusgate-agent-linux-${arch}" ]]; then
cp -a "${NG_LOCAL_SRC}/agent-go/nexusgate-agent-linux-${arch}" "$out"
else
curl -fL --retry 3 "${GIT_BASE}/releases/download/${AGENT_RELEASE}/nexusgate-agent-linux-${arch}" -o "$out"
fi
[[ -s "$out" ]] || die 'Agent 二进制下载不完整'
}
raw_fetch scripts/agent-uninstall.sh "$tmp_dir/uninstall.sh"
raw_fetch scripts/agent-doctor.sh "$tmp_dir/doctor.sh"
raw_fetch scripts/agent-cert.sh "$tmp_dir/cert.sh"
raw_fetch scripts/agent-update.sh "$tmp_dir/update.sh"
raw_fetch scripts/agent-singbox.sh "$tmp_dir/singbox.sh"
raw_fetch scripts/agent-logrotate.conf "$tmp_dir/logrotate.conf"
raw_fetch scripts/agent-logrotate-setup.sh "$tmp_dir/logrotate-setup.sh"
[[ -s "$tmp_dir/update.sh" ]] || die 'Agent 升级脚本下载不完整'
if [[ "$TARGET_IMPL" == "go" ]]; then
fetch_agent_binary "$tmp_dir/nexusgate-agent"
else
raw_fetch agent/agent.js "$tmp_dir/agent.js"
raw_fetch agent/run.sh "$tmp_dir/run.sh"
node --check "$tmp_dir/agent.js"
fi
# Updating restarts sing-box. Persist its current bidirectional counters
# before the running process is replaced.
(
set -a; source /etc/nexusgate/agent.env; set +a
if [[ "$CURRENT_IMPL" == "go" ]]; then
/opt/nexusgate-agent/nexusgate-agent flush-usage
else
node /opt/nexusgate-agent/agent.js flush-usage
fi
) || die '更新前流量统计上报失败,保留原 Agent;检查控制面连接和 ng-agent doctor 后重试'
if [[ "$TARGET_IMPL" == "go" ]]; then
install -m 0755 "$tmp_dir/nexusgate-agent" /opt/nexusgate-agent/nexusgate-agent
else
install -m 0644 "$tmp_dir/agent.js" /opt/nexusgate-agent/agent.js
install -m 0755 "$tmp_dir/run.sh" /opt/nexusgate-agent/run.sh
fi
install -m 0755 "$tmp_dir/uninstall.sh" /usr/local/sbin/ng-agent-uninstall
install -m 0755 "$tmp_dir/doctor.sh" /usr/local/sbin/ng-agent-doctor
install -m 0755 "$tmp_dir/cert.sh" /usr/local/sbin/ng-agent-cert
install -m 0755 "$tmp_dir/singbox.sh" /usr/local/sbin/ng-agent-singbox
install -m 0644 "$tmp_dir/logrotate.conf" /etc/nexusgate/agent-logrotate.conf
install -m 0755 "$tmp_dir/logrotate-setup.sh" /usr/local/sbin/ng-agent-logrotate-setup
install -m 0755 "$tmp_dir/update.sh" /usr/local/sbin/ng-agent-update.next
mv -f -- /usr/local/sbin/ng-agent-update.next /usr/local/sbin/ng-agent-update
cat > /usr/local/sbin/ng-agent <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
case "${1:-}" in
update) exec ng-agent-update ;;
uninstall) shift; exec ng-agent-uninstall "$@" ;;
doctor|status) exec ng-agent-doctor ;;
cert) shift; exec ng-agent-cert "$@" ;;
engine) shift; exec ng-agent-singbox "$@" ;;
*) printf 'NexusGate Agent: ng-agent doctor | ng-agent cert | ng-agent engine install | ng-agent update | ng-agent uninstall\n' ;;
esac
EOF
chmod 0755 /usr/local/sbin/ng-agent
# sing-box 是唯一的入口引擎;缺失时直接安装。
if [[ ! -x /usr/local/bin/nexusgate-sing-box || ! -x /usr/local/bin/nexusgate-sing-box-stats ]]; then
NG_REPO="$REPO" NG_BRANCH="$BRANCH" ng-agent-singbox install \
|| die 'sing-box 引擎安装失败;修复后运行 ng-agent engine install 重试'
fi
if command -v systemctl >/dev/null && [[ -d /run/systemd/system ]]; then
raw_fetch systemd/nexusgate-agent.service "$tmp_dir/nexusgate-agent.service"
raw_fetch systemd/nexusgate-sing-box.service "$tmp_dir/nexusgate-sing-box.service"
install -m 0644 "$tmp_dir/nexusgate-agent.service" /etc/systemd/system/nexusgate-agent.service
install -m 0644 "$tmp_dir/nexusgate-sing-box.service" /etc/systemd/system/nexusgate-sing-box.service
if [[ "$TARGET_IMPL" == "node" ]]; then
# 仓库里的 unit 默认指向 Go 二进制;Node 实现改为经 run.sh 启动
sed -i 's|^ExecStart=.*|ExecStart=/opt/nexusgate-agent/run.sh|' /etc/systemd/system/nexusgate-agent.service
fi
systemctl daemon-reload
rm -f -- /etc/nexusgate/last-heartbeat.json
systemctl restart nexusgate-agent.service
systemctl is-active --quiet nexusgate-agent.service || die "Agent 重启失败"
elif command -v rc-service >/dev/null; then
raw_fetch openrc/nexusgate-agent "$tmp_dir/openrc-agent"
raw_fetch openrc/nexusgate-sing-box "$tmp_dir/openrc-sing-box"
install -m 0755 "$tmp_dir/openrc-agent" /etc/init.d/nexusgate-agent
install -m 0755 "$tmp_dir/openrc-sing-box" /etc/init.d/nexusgate-sing-box
if [[ "$TARGET_IMPL" == "node" ]]; then
# 仓库里的 OpenRC 服务默认指向 Go 二进制;Node 实现改为经 run.sh 启动
sed -i 's|^command=.*|command="/opt/nexusgate-agent/run.sh"|' /etc/init.d/nexusgate-agent
fi
if [[ -e /etc/init.d/crond ]]; then
rc-update add crond default >/dev/null 2>&1 || true
rc-service crond start >/dev/null 2>&1 || true
fi
rm -f -- /etc/nexusgate/last-heartbeat.json
rc-service nexusgate-agent restart
rc-service nexusgate-agent status >/dev/null || die "Agent 重启失败"
else
die "未检测到 systemd 或 OpenRC"
fi
ng-agent-logrotate-setup
for _ in {1..35}; do
[[ -s /etc/nexusgate/last-heartbeat.json ]] && break
sleep 1
done
[[ -s /etc/nexusgate/last-heartbeat.json ]] || die 'Agent 已重启,但尚未连接控制面;请执行 ng-agent doctor'
info "Agent 更新完成"