Files
NexusGate/scripts/agent-doctor.sh
T

98 lines
5.2 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 -u
[[ "${EUID}" -eq 0 ]] || { printf '请使用 root 运行\n' >&2; exit 1; }
[[ -r /etc/nexusgate/agent.env ]] || { printf '未安装 NexusGate Agent\n' >&2; exit 1; }
# Local root-owned configuration. Never print the enrollment key.
source /etc/nexusgate/agent.env
printf '控制面:%s\n' "${NG_CONTROLLER:-未配置}"
printf '已验证节点证书:'
node -e 'const domains=require("/opt/nexusgate-agent/agent.js").installedCertificates();console.log(domains.length?domains.join(", "):"暂无;运行 ng-agent cert")' 2>&1 || true
printf 'Agent 版本:'
node -p "require('fs').readFileSync('/opt/nexusgate-agent/agent.js','utf8').match(/const VERSION = '([^']+)'/)[1]" 2>/dev/null || printf '无法读取\n'
has_xray_resources=1
if ! node -e 'const fs=require("fs");const dir="/etc/nexusgate/xray/resources";process.exit(fs.readdirSync(dir).some(name=>name.endsWith(".json")&&JSON.parse(fs.readFileSync(`${dir}/${name}`)).engine!=="sing-box")?0:1)' 2>/dev/null; then
has_xray_resources=0
printf '这台机器没有 Xray 资源,Xray 空闲服务停止属于正常(AnyTLS 由 sing-box 运行)。\n'
fi
if command -v systemctl >/dev/null && [[ -d /run/systemd/system ]]; then
for name in nexusgate-agent nexusgate-xray nexusgate-sing-box; do
printf '%s:' "$name"
systemctl is-active "$name" 2>&1 || true
done
else
rc-service nexusgate-agent status || true
rc-service nexusgate-xray status || true
rc-service nexusgate-sing-box status || true
fi
printf '\nsing-box 构建与配置:\n'
if [[ -x /usr/local/bin/nexusgate-sing-box && ! -x /usr/local/bin/nexusgate-sing-box-stats ]]; then
printf 'sing-box 主程序存在但统计组件缺失;安装不完整,运行 ng-agent engine install 重试。\n'
elif [[ -x /usr/local/bin/nexusgate-sing-box ]]; then
/usr/local/bin/nexusgate-sing-box version | head -n 4
if [[ -f /etc/nexusgate/sing-box/config.json ]]; then
/usr/local/bin/nexusgate-sing-box check -c /etc/nexusgate/sing-box/config.json 2>&1 | tail -n 12
printf 'AnyTLS 入站流量统计(累计):\n'
/usr/local/bin/nexusgate-sing-box-stats --server="127.0.0.1:${NG_SINGBOX_API_PORT:-10086}" 2>&1 | head -c 900
printf '\n'
else
printf '已安装,当前没有 AnyTLS 资源\n'
fi
else
printf '未安装;运行 ng-agent engine install\n'
fi
printf '控制面连通性:'
curl --max-time 8 -fsS "${NG_CONTROLLER%/}/healthz" 2>&1 | head -c 350 || true
printf '\nXray 配置校验:\n'
if [[ -f /etc/nexusgate/xray/config.json ]]; then
/usr/local/bin/xray run -test -config /etc/nexusgate/xray/config.json 2>&1 | tail -n 12
else
printf '配置文件不存在\n'
fi
printf '\nHysteria 2 UDP 监听:\n'
node <<'NODE' 2>&1 || true
const fs = require('node:fs');
const agent = require('/opt/nexusgate-agent/agent.js');
const dir = '/etc/nexusgate/xray/resources';
const resources = fs.readdirSync(dir).filter((name) => name.endsWith('.json'))
.map((name) => JSON.parse(fs.readFileSync(`${dir}/${name}`, 'utf8')));
const expected = resources.flatMap((resource) => resource.inbounds || [])
.filter((inbound) => inbound.protocol === 'hysteria').map((inbound) => inbound.port);
if (!expected.length) console.log('没有 Hysteria 2 入站');
else {
const config = JSON.parse(fs.readFileSync('/etc/nexusgate/xray/config.json', 'utf8'));
for (const port of expected) {
const inbound = config.inbounds.find((item) => item.port === port && item.protocol === 'hysteria');
console.log(`UDP ${port}: 传输 ${inbound?.streamSettings?.network || '未配置'},账户 ${(inbound?.settings?.clients || inbound?.settings?.users || []).length}`);
}
try {
const missing = agent.missingHysteriaListeners(resources);
console.log(missing.length ? `未监听 UDP: ${missing.join(', ')}` : '所有 Hysteria 2 UDP 端口均由 Xray 监听');
} catch (error) { console.log(`监听检查失败: ${error.message}`); }
}
NODE
printf '\nXray 入站流量统计(累计,查询不会清零):\n'
if [[ "$has_xray_resources" == 0 ]]; then
printf '无 Xray 入口,跳过统计查询。\n'
else
stats_output="$(/usr/local/bin/xray api statsquery --server="127.0.0.1:${NG_XRAY_API_PORT:-10085}" -pattern 'inbound>>>' 2>&1)"
if [[ $? -ne 0 ]]; then
printf '查询失败:%.250s\n' "$stats_output"
else
STATS_OUTPUT="$stats_output" node -e '
try {
const stats = JSON.parse(process.env.STATS_OUTPUT).stat || [];
const entries = stats.filter(item => /^inbound>>>ng-.*>>>traffic>>>(uplink|downlink)$/.test(item.name));
if (!entries.length) console.log("尚无入口流量计数;请确认客户端确实连接本机节点后再测试");
else for (const item of entries.slice(0, 24)) console.log(`${item.name}: ${item.value === undefined ? 0 : item.value} B`);
} catch { console.log("统计返回格式无效,请升级 Xray 和 Agent"); }
'
fi
fi
printf '\n最近 Agent 与 Xray 日志:\n'
if command -v journalctl >/dev/null && [[ -d /run/systemd/system ]]; then
journalctl -u nexusgate-agent -u nexusgate-xray -u nexusgate-sing-box -n 45 --no-pager -o short-iso 2>&1 | sed -E 's/(Bearer |NG_AGENT_KEY=)[^[:space:]]+/\1[REDACTED]/g; s/[Pp]rivate[[:space:]]*[Kk]ey:[[:space:]]*[^[:space:]]+/PrivateKey: [REDACTED]/g'
else
tail -n 45 /var/log/nexusgate/xray-error.log 2>/dev/null || true
fi