feat(install-agent): 启动前探测主控注册接口(404/连不上即中止),改为 systemd/OpenRC 服务化安装带自启
This commit is contained in:
+174
-11
@@ -2,11 +2,17 @@
|
||||
# 3x-ui-agent 节点一键安装脚本
|
||||
# 用法: bash install-agent.sh --master http://MASTER_IP:2053 --token YOUR_AGENT_TOKEN [--name my-node]
|
||||
# 要求: Debian/Ubuntu/Alpine/CentOS (amd64/arm64), root 运行
|
||||
#
|
||||
# 测试用环境变量(一般无需设置):
|
||||
# XUI_ROOT 安装路径前缀(假根目录验证用),默认空 = 真实路径
|
||||
# XUI_INIT_SYSTEM 强制 init 系统: systemd | openrc | none,默认 auto 探测
|
||||
# XUI_URL agent 二进制下载地址覆盖
|
||||
|
||||
set -e
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; NC='\033[0m'
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; NC='\033[0m'
|
||||
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
||||
|
||||
[[ $EUID -ne 0 ]] && error "请用 root 运行"
|
||||
@@ -35,15 +41,20 @@ esac
|
||||
XUI_URL="${XUI_URL:-https://git.881218.xyz/rogue/3x-ui-agent/releases/download/v3.7.0-agent.1/x-ui-linux-${BIN_ARCH}}"
|
||||
XRAY_VER="26.6.27"
|
||||
|
||||
ROOT="${XUI_ROOT:-}"
|
||||
XUI_HOME="${ROOT}/usr/local/x-ui"
|
||||
CONF_DIR="${ROOT}/etc/x-ui"
|
||||
AGENT_BIN="${XUI_HOME}/x-ui"
|
||||
|
||||
info "创建目录..."
|
||||
mkdir -p /usr/local/x-ui/bin /etc/x-ui
|
||||
mkdir -p "${XUI_HOME}/bin" "${CONF_DIR}"
|
||||
|
||||
info "下载 agent 二进制..."
|
||||
curl -fL -o /usr/local/x-ui/x-ui "$XUI_URL" || error "agent 下载失败"
|
||||
chmod +x /usr/local/x-ui/x-ui
|
||||
curl -fL -o "${AGENT_BIN}" "$XUI_URL" || error "agent 下载失败"
|
||||
chmod +x "${AGENT_BIN}"
|
||||
|
||||
info "下载 xray v${XRAY_VER}..."
|
||||
cd /usr/local/x-ui/bin
|
||||
cd "${XUI_HOME}/bin"
|
||||
case "$BIN_ARCH" in
|
||||
amd64) XRAY_ZIP="Xray-linux-64.zip";;
|
||||
arm64) XRAY_ZIP="Xray-linux-arm64-v8a.zip";;
|
||||
@@ -55,22 +66,166 @@ rm -f "$XRAY_ZIP"
|
||||
info "下载 geo 文件..."
|
||||
curl -fL -o geoip.dat "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat" || error "geoip 下载失败"
|
||||
curl -fL -o geosite.dat "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" || error "geosite 下载失败"
|
||||
cd - >/dev/null
|
||||
|
||||
info "写入 agent 配置..."
|
||||
cat > /etc/x-ui/agent.json <<EOF
|
||||
cat > "${CONF_DIR}/agent.json" <<EOF
|
||||
{
|
||||
"master_url": "$MASTER",
|
||||
"token": "$TOKEN",
|
||||
"node_name": "$NAME"
|
||||
}
|
||||
EOF
|
||||
chmod 600 /etc/x-ui/agent.json
|
||||
chmod 600 "${CONF_DIR}/agent.json"
|
||||
|
||||
info "启动 agent..."
|
||||
pkill -f "/usr/local/x-ui/x-ui agent" 2>/dev/null || true; sleep 1
|
||||
nohup /usr/local/x-ui/x-ui agent > /tmp/agent.log 2>&1 &
|
||||
# 探测主控可达性:拿假 token 打一次注册接口,在启动前把地址问题拦下来,
|
||||
# 别让 agent 带着必死的配置装完再无声无息地死掉(主控上一直显示"未知")。
|
||||
# 404 → 注册路由不存在,主控地址大概率少了面板基础路径
|
||||
# 连不上 → 网络/域名/TLS 问题
|
||||
# 其他(401等) → 路由存在(假 token 被拒正是预期),路径正确
|
||||
probe_master() {
|
||||
local url="${MASTER%/}/panel/api/agent/register"
|
||||
info "探测主控注册接口: $url"
|
||||
local code
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 -X POST "$url" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer install-probe-invalid-token' \
|
||||
-d '{"token":"install-probe-invalid-token","name":"install-probe"}' 2>/dev/null) || code="000"
|
||||
case "$code" in
|
||||
404)
|
||||
echo ""
|
||||
echo -e "${RED}============================================================${NC}"
|
||||
echo -e "${RED} 主控返回 404:注册接口不存在,安装中止。${NC}"
|
||||
echo -e "${RED} 主控地址大概率少了面板基础路径(如 /rogue)。${NC}"
|
||||
echo -e "${RED} 当前地址: ${MASTER}${NC}"
|
||||
echo -e "${RED} 若面板实际地址带基础路径,请改用 --master ${MASTER%/}/rogue${NC}"
|
||||
echo -e "${RED} 之类的完整地址(以面板真实基础路径为准)改对后重跑本脚本。${NC}"
|
||||
echo -e "${RED}============================================================${NC}"
|
||||
exit 1
|
||||
;;
|
||||
000)
|
||||
echo ""
|
||||
echo -e "${RED}============================================================${NC}"
|
||||
echo -e "${RED} 连不上主控,安装中止。${NC}"
|
||||
echo -e "${RED} 请检查:网络是否通、域名解析是否正常、主控地址与端口是否写对、${NC}"
|
||||
echo -e "${RED} 以及主控 HTTPS 证书是否有效(agent 不接受自签证书)。${NC}"
|
||||
echo -e "${RED} 目标: $url${NC}"
|
||||
echo -e "${RED}============================================================${NC}"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
info "主控探测通过 (HTTP $code,注册路由存在)"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
probe_master
|
||||
|
||||
detect_init_system() {
|
||||
case "${XUI_INIT_SYSTEM:-auto}" in
|
||||
systemd|openrc|none) echo "${XUI_INIT_SYSTEM}"; return;;
|
||||
esac
|
||||
if [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
|
||||
echo systemd; return
|
||||
fi
|
||||
if command -v rc-update >/dev/null 2>&1 && command -v rc-service >/dev/null 2>&1; then
|
||||
echo openrc; return
|
||||
fi
|
||||
echo none
|
||||
}
|
||||
|
||||
# 以 systemd 服务方式安装并启动(开机自启)
|
||||
start_via_systemd() {
|
||||
local unit_dir="${ROOT}/etc/systemd/system"
|
||||
mkdir -p "$unit_dir"
|
||||
cat > "${unit_dir}/x-ui-agent.service" <<'EOF'
|
||||
[Unit]
|
||||
Description=3x-ui agent
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/x-ui/x-ui agent
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
info "已生成 systemd 服务文件: ${unit_dir}/x-ui-agent.service"
|
||||
if [ -n "$ROOT" ]; then
|
||||
info "(XUI_ROOT 模式:跳过 systemctl 实际操作)"
|
||||
return 0
|
||||
fi
|
||||
systemctl stop x-ui-agent 2>/dev/null || true
|
||||
pkill -f "${AGENT_BIN} agent" 2>/dev/null || true; sleep 1
|
||||
systemctl daemon-reload
|
||||
systemctl enable x-ui-agent
|
||||
systemctl restart x-ui-agent
|
||||
sleep 2
|
||||
if systemctl is-active --quiet x-ui-agent; then
|
||||
info "agent 已由 systemd 托管启动(开机自启)"
|
||||
echo ""
|
||||
echo " 主控: $MASTER"
|
||||
echo " 节点名: $NAME"
|
||||
echo " 日志: journalctl -u x-ui-agent -f"
|
||||
echo " agent 会在 30 秒内从主控拉取配置"
|
||||
else
|
||||
error "agent 服务启动失败,查看: systemctl status x-ui-agent"
|
||||
fi
|
||||
}
|
||||
|
||||
# 以 OpenRC 服务方式安装并启动(开机自启,Alpine 等)
|
||||
start_via_openrc() {
|
||||
local init_dir="${ROOT}/etc/init.d"
|
||||
mkdir -p "$init_dir"
|
||||
cat > "${init_dir}/x-ui-agent" <<'EOF'
|
||||
#!/sbin/openrc-run
|
||||
|
||||
name="x-ui-agent"
|
||||
description="3x-ui lightweight node agent"
|
||||
command="/usr/local/x-ui/x-ui"
|
||||
command_args="agent"
|
||||
command_background="yes"
|
||||
pidfile="/run/x-ui-agent.pid"
|
||||
output_log="/var/log/x-ui-agent.log"
|
||||
error_log="/var/log/x-ui-agent.log"
|
||||
|
||||
depend() {
|
||||
need net
|
||||
}
|
||||
EOF
|
||||
chmod +x "${init_dir}/x-ui-agent"
|
||||
info "已生成 OpenRC 服务文件: ${init_dir}/x-ui-agent"
|
||||
if [ -n "$ROOT" ]; then
|
||||
info "(XUI_ROOT 模式:跳过 rc-update/rc-service 实际操作)"
|
||||
return 0
|
||||
fi
|
||||
rc-service x-ui-agent stop 2>/dev/null || true
|
||||
pkill -f "${AGENT_BIN} agent" 2>/dev/null || true; sleep 1
|
||||
rc-update add x-ui-agent default
|
||||
rc-service x-ui-agent restart
|
||||
sleep 2
|
||||
if rc-service x-ui-agent status >/dev/null 2>&1; then
|
||||
info "agent 已由 OpenRC 托管启动(开机自启)"
|
||||
echo ""
|
||||
echo " 主控: $MASTER"
|
||||
echo " 节点名: $NAME"
|
||||
echo " 日志: tail -f /var/log/x-ui-agent.log"
|
||||
echo " agent 会在 30 秒内从主控拉取配置"
|
||||
else
|
||||
error "agent 服务启动失败,查看: rc-service x-ui-agent status"
|
||||
fi
|
||||
}
|
||||
|
||||
# 无服务管理器时回落 nohup(无开机自启,明确警告)
|
||||
start_via_nohup() {
|
||||
warn "未检测到 systemd / OpenRC,退回 nohup 方式启动"
|
||||
warn "注意:nohup 方式没有开机自启,机器重启后 agent 不会自动恢复,需手动重跑本脚本!"
|
||||
pkill -f "${AGENT_BIN} agent" 2>/dev/null || true; sleep 1
|
||||
# -config 显式给出(生产环境即其默认路径 /etc/x-ui/agent.json,行为不变),
|
||||
# 这样 XUI_ROOT 假根验证时 agent 也能找到刚写下的配置。
|
||||
nohup "${AGENT_BIN}" agent -config "${CONF_DIR}/agent.json" > /tmp/agent.log 2>&1 &
|
||||
sleep 8
|
||||
|
||||
if grep -q "Starting 3x-ui agent" /tmp/agent.log 2>/dev/null; then
|
||||
info "agent 启动成功!"
|
||||
echo ""
|
||||
@@ -81,3 +236,11 @@ if grep -q "Starting 3x-ui agent" /tmp/agent.log 2>/dev/null; then
|
||||
else
|
||||
error "启动失败,查看日志: cat /tmp/agent.log"
|
||||
fi
|
||||
}
|
||||
|
||||
info "启动 agent..."
|
||||
case "$(detect_init_system)" in
|
||||
systemd) start_via_systemd;;
|
||||
openrc) start_via_openrc;;
|
||||
*) start_via_nohup;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user