🌙

一、问题现象

你看到内存显示为 "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。

修复方法

  1. 在数据库中添加 memoryUsedMbmemoryTotalMb 字段

  2. 修改代码,当值为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}'

工作原理

  1. cat /proc/meminfo 读取系统内存信息

  2. /MemTotal:/{t=$2} 提取总内存(KB)

  3. /MemAvailable:/{a=$2} 提取可用内存(KB)

  4. END{print t-a, t, a} 输出:已用内存、总内存、可用内存

/proc/meminfo 示例输出

MemTotal:        7868416 kB
MemFree:         5565440 kB
MemAvailable:   5831680 kB
Buffers:           58808 kB
Cached:           451988 kB
...

四、代码修改位置

文件修改内容
hostMetricsCollector.ts 内存获取命令改为/proc/meminfo方式
hostMetricsCollector.ts 解析逻辑从MB改为KB(/proc/meminfo返回KB)
hostMetricsCollector.ts 存储时转换为MB(Math.round(memUsedKb / 1024)
monitorController.ts 移除16GB硬编码默认值
Host.ts 添加memoryUsedMbmemoryTotalMb模型字段

五、修复后的效果

修复前:

  • 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更可靠?

  1. 跨发行版兼容:所有Linux发行版都支持,格式统一

  2. 内核标准接口:直接读取内核数据,不依赖free命令的版本差异

  3. 数据更准确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}'

优势

  1. 内核原生接口:直接读取内核数据,不依赖任何第三方工具

  2. 格式绝对统一MemTotal:MemAvailable: 字段名在所有Linux内核版本中都一致

  3. 数据更准确MemAvailable 包含了可回收的buff/cache


验证结果

从数据库中可以看到,修复后:

服务器系统内存使用率总内存
server0-01 CentOS 59% 1.56 GB
server-03 Ubuntu 23% 7.52 GB

两个不同系统都能正确显示!


总结

方案兼容性可靠性
旧方案 (free -m) ❌ 依赖命令版本,可能不兼容
新方案 (/proc/meminfo) ✅ 所有Linux发行版通用

 

posted on 2026-07-10 19:35  星火撩原  阅读(2)  评论(0)    收藏  举报

本站已运行:0
🌙 夜间模式
🌙
🌙