一、问题现象
你看到内存显示为 "0.6 GB / 16 GB",但实际上你的服务器内存并不是16GB,而且Ubuntu机器内存显示为 0%。
二、根本原因分析
原因1:数据库缺少字段(导致显示16GB默认值)
之前的代码中,前端显示内存总量时使用了硬编码的默认值:
// monitorController.ts 原始代码
total: (host.memoryTotalMb || 16384) * 1024 * 1024, // 默认16384 MB = 16 GB
但数据库hosts表中根本没有memoryTotalMb字段,所以这个值始终是0,就使用了默认值16GB。
修复方法:
-
在数据库中添加
memoryUsedMb和memoryTotalMb字段 -
修改代码,当值为0时不再使用默认值,而是显示真实数据
原因2:Ubuntu系统命令兼容性问题(导致显示0%)
这是更关键的问题。原代码使用的内存获取命令是:
free -m | grep Mem | awk '{print ($2-$7), $2, $7}'
问题:不同Linux发行版的free -m输出格式不同!
CentOS/RHEL格式(第7列是available):
total used free shared buff/cache available
Mem: 1594 947 87 9 559 647
Ubuntu格式(第7列可能不存在或含义不同):
total used free shared buff/cache available
Mem: 7695 1753 5430 25 511 5693
Ubuntu的free命令输出中,available列的位置可能不同,或者某些版本的输出格式不一致,导致$7获取到错误的值。
三、最终解决方案
改用 /proc/meminfo 文件,这是Linux内核提供的标准接口,所有发行版格式统一。
修改后的命令:
cat /proc/meminfo | awk '/MemTotal:/{t=$2}/MemAvailable:/{a=$2}END{print t-a, t, a}'
工作原理:
-
cat /proc/meminfo读取系统内存信息 -
/MemTotal:/{t=$2}提取总内存(KB) -
/MemAvailable:/{a=$2}提取可用内存(KB) -
END{print t-a, t, a}
/proc/meminfo 示例输出:
MemTotal: 7868416 kB
MemFree: 5565440 kB
MemAvailable: 5831680 kB
Buffers: 58808 kB
Cached: 451988 kB
...
四、代码修改位置
| 文件 | 修改内容 |
|---|---|
内存获取命令改为/proc/meminfo方式 |
|
解析逻辑从MB改为KB(/proc/meminfo返回KB) |
|
存储时转换为MB(Math.round(memUsedKb / 1024)) |
|
| 移除16GB硬编码默认值 | |
添加memoryUsedMb和memoryTotalMb模型字段 |
五、修复后的效果
修复前:
-
server-03 (Ubuntu): 0% / 0 B / 1 MB ❌
修复后:
-
server-03 (Ubuntu): 23% / 1.71 GB / 7.52 GB ✅
-
server0-01: 59% / 0.93 GB / 1.56 GB ✅
六、为什么用/proc/meminfo更可靠?
-
跨发行版兼容:所有Linux发行版都支持,格式统一
-
内核标准接口:直接读取内核数据,不依赖
free命令的版本差异 -
数据更准确:
MemAvailable包含了可回收的buff/cache,反映真实可用内存
为什么不会影响其他系统?
/proc/meminfo 是 Linux 内核标准接口
/proc/meminfo 是 Linux 内核提供的标准伪文件系统,所有符合 POSIX 标准的 Linux 发行版都支持,包括:
| 发行版 | 版本 | 支持情况 |
|---|---|---|
| CentOS | 6/7/8/9 | ✅ 完全支持 |
| openEuler(欧拉) | 20.03/22.03/24.03 | ✅ 完全支持 |
| Ubuntu | 16.04+ | ✅ 完全支持 |
| Debian | 8+ | ✅ 完全支持 |
| Fedora | 20+ | ✅ 完全支持 |
| SUSE | 11+ | ✅ 完全支持 |
之前的问题恰恰是因为用了不兼容的命令
旧命令(有兼容性问题):
free -m | grep Mem | awk '{print ($2-$7), $2, $7}'
free 命令的输出格式取决于 procps-ng 包的版本,不同发行版可能不同:
-
CentOS 7 的
free输出中,available是第7列 -
Ubuntu 22.04 的
free输出中,列位置可能不同 -
某些精简版系统甚至可能没有
free命令
新方案的优势
新命令(跨发行版兼容):
cat /proc/meminfo | awk '/MemTotal:/{t=$2}/MemAvailable:/{a=$2}END{print t-a, t, a}'
优势:
-
内核原生接口:直接读取内核数据,不依赖任何第三方工具
-
格式绝对统一:
MemTotal:和MemAvailable:字段名在所有Linux内核版本中都一致 -
数据更准确:
MemAvailable包含了可回收的buff/cache
验证结果
从数据库中可以看到,修复后:
| 服务器 | 系统 | 内存使用率 | 总内存 |
|---|---|---|---|
| server0-01 | CentOS | 59% | 1.56 GB |
| server-03 | Ubuntu | 23% | 7.52 GB |
两个不同系统都能正确显示!
总结
| 方案 | 兼容性 | 可靠性 |
|---|---|---|
旧方案 (free -m) |
❌ 依赖命令版本,可能不兼容 | 低 |
新方案 (/proc/meminfo) |
✅ 所有Linux发行版通用 | 高 |
浙公网安备 33010602011771号