98 lines
5.2 KiB
Bash
98 lines
5.2 KiB
Bash
#!/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
|