Files
NetMesh/electron/bridges/inspection/adapters/linuxServerAdapter.cjs
zhaolei c64e00d835 feat: 新增设备巡检模块实现完整的巡检告警功能
新增设备巡检模块核心功能,包括:
- 巡检数据存储与调度系统
- 华为/H3C交换机及Linux服务器采集器
- 设备扩展配置与告警规则管理
- 主机详情页巡检配置入口
- 产品名称自定义设置功能
- 网络设备SSH exec通道兼容处理
2026-10-09 10:37:48 +08:00

103 lines
2.9 KiB
JavaScript
Raw Permalink 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.
"use strict";
/**
* Linux 服务器采集器
*
* 采集指标(告警相关):
* - cpu_usage CPU 使用率(%)
* - memory_usage 内存使用率(%)
* - disk_usage 磁盘使用率(%,只显示超过 80% 的挂载点)
*
* 实现说明:
* 直接使用 POSIX shell 命令,命令与 NetMesh System Manager 的概览一致。
* 传入 exec 函数来执行远程命令(由调度器注入,复用 SSH 连接池)。
*/
const BaseAdapter = require("./baseAdapter.cjs");
class LinuxServerAdapter extends BaseAdapter {
constructor(connectionInfo, options = {}) {
super(connectionInfo, options);
this.adapterName = "linux_server";
// 支持外部注入 exec 函数(用于复用 SSH 连接)
if (options.execFn) {
this.execute = options.execFn;
}
}
getSupportedMetrics() {
return [
"cpu_usage",
"memory_usage",
"disk_usage",
];
}
async collectMetrics() {
const metrics = {};
const raw = {};
// 1. CPU 使用率(采样 top)
try {
raw.cpu = await this.execute("top -bn1 2>/dev/null | head -n 5");
const cpuMatch = (raw.cpu || "").match(/Cpu\(s\):\s*([\d.]+)\s*us,\s*([\d.]+)\s*sy/i);
if (cpuMatch) {
metrics.cpu_usage = Math.round(parseFloat(cpuMatch[1]) + parseFloat(cpuMatch[2]));
}
} catch (e) {
throw e; // SSH 失败或其他错误必须向上传播
}
// 2. 内存使用率
try {
raw.mem = await this.execute("free -k 2>/dev/null | head -n 2 | tail -n 1");
// 支持中英文输出: "Mem:" 或 "内存:"
const memMatch = (raw.mem || "").match(/(?:Mem:|内存[::])\s+(\d+)\s+(\d+)/);
if (memMatch) {
const total = parseInt(memMatch[1], 10);
const used = parseInt(memMatch[2], 10);
if (total > 0) {
metrics.memory_usage = Math.min(100, Math.round((used / total) * 100));
}
}
} catch (e) {
throw e;
}
// 3. 磁盘使用率(显示所有挂载点)
try {
raw.disk = await this.execute("df -h 2>/dev/null | tail -n +2 | grep -v '/dev/loop'");
const disks = this.parseDiskUsage(raw.disk);
if (disks.length > 0) metrics.disk_usage = disks;
} catch (e) {
throw e;
}
return metrics;
}
/**
* 解析磁盘使用率(df -h 输出格式),返回所有挂载点
*/
parseDiskUsage(text) {
const disks = [];
const lines = (text || "").split("\n");
for (const line of lines) {
const parts = line.trim().split(/\s+/);
if (parts.length < 6) continue;
const usageStr = parts[4] || "";
const usageMatch = usageStr.match(/^(\d+)%/);
if (!usageMatch) continue;
const usagePercent = parseInt(usageMatch[1], 10);
disks.push({
filesystem: parts[0],
usage_percent: usagePercent,
mount: parts[parts.length - 1],
});
}
return disks;
}
}
module.exports = LinuxServerAdapter;