ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Linux性能排障利器nmon:CPU、内存与磁盘IO监控实战指南

2026/9/28 12:09:14 拓冰建站 浏览量
Linux性能排障利器nmon:CPU、内存与磁盘IO监控实战指南 线上应用突然卡顿、CPU飙到 90% 却一时说不清瓶颈到底在 CPU、内存还是磁盘 IO 时我最先敲下去的命令往往不是 top而是 nmon。nmonNigels Monitor是一款老牌的 Linux 综合监控工具单文件、无依赖、部署极简打开终端就能同时看到 CPU、内存、网络、磁盘、文件系统、进程甚至内核运行队列的数据。它既能在交互界面实时观察也能以后台采集模式把指标落盘成 .nmon 文件供事后用 Excel 模板或图表工具分析。这篇文章就是我在服务器排障、压测摸底、嵌入式 ARM 设备AArch64社区里常写作 arrch64上多年用 nmon 的完整经验汇总适合刚接触 Linux 运维的人也适合手里攒了一堆 .nmon 文件但不知道怎么高效利用的老手。1. 在监控矩阵里 nmon 的位置为什么应急排障时我总先敲它1.1 和 top、sar、Prometheus 这些工具比nmon 强在哪现在监控栈越来越重Prometheus 加 Grafana 几乎是标配但真到了单机应急那一两分钟nmon 仍然是最顺手的工具。top 只能交互式看进程sar 虽然能回溯历史但默认没开Prometheus 要部署 exporter 还要等抓取周期。nmon 不需要 agent不需要服务端不需要往业务容器里塞探针一个二进制文件扔上去就能跑数据格式又是纯文本后面想用 awk、Python 二次处理都很方便。不过 nmon 解决的核心问题不是“长期趋势”而是“当前这台机器到底哪一项先被打满”。它能在同一个滚动界面里把 CPU、内存、磁盘、网络全部铺开并且随着刷新实时变化。我记得有一次压测业务方坚持说数据库连接池不够我打开 nmon 看了一眼磁盘 BUSY 指标直接飙到 85%再按一下 t 看进程发现其实是日志同步线程在刷盘根本不是连接池的问题。这种多维度同时可见的特性正是 nmon 不可替代的地方。1.2 轻量、可移植、跨架构决定了它的适用范围nmon 的轻量体现在两个层面。一是运行时开销低正常情况下对 CPU 的消耗几乎可以忽略不计二是部署成本低二进制拷贝过去就能执行。到了嵌入式 Linux 或者国产化环境资源紧张、没有包管理器或不能随便联网安装时nmon 依然能用我用过它在 ARM64 的小盒子、兆芯 x86 工控机上跑过只要 /proc 虚拟文件系统还在nmon 就能拿到 CPU、内存和磁盘的数据。我在 ARM 设备上有一个很深的体会很多监控工具在 x86 上有现成包一到 AArch64 就要重新编译而 nmon 官方一直提供多架构构建就算默认源里没有源码也只有一个 C 文件交叉编译成本很低。对于嵌入式 Linux 场景比如 CNC 控制设备、PLC 网关这种机型nmon 是少数能在老内核上稳定跑起来的监控工具之一。这也解释了为什么这么多年过去了nmon 依然活跃在 Linux 常用命令清单和运维面试题里因为它解决的问题太实在。2. 从安装到验证包管理器、静态二进制与 ARM64 适配2.1 各大发行版的安装套路多数发行版仓库里都有 nmon名字就叫 nmon不需要额外加第三方源。RHEL、CentOS、Rocky、AlmaLinux 这类系统先确保 EPEL 仓库可用然后执行sudo dnf install epel-release再执行sudo dnf install nmon。如果网络环境受限也可以直接找静态编译版本。Ubuntu、Debian 更简单sudo apt update sudo apt install nmon即可。openSUSE 系用sudo zypper install nmon。常规 Linux 服务器如果没法装包直接从官网或可信镜像下载编译好的二进制chmod x 之后放到 /usr/local/bin 就能跑。我自己的经验是尽量用发行版源里的版本因为构建参数和当前内核匹配度更稳省去自己折腾的麻烦。安装完成后验证是否可用直接执行nmon能打开交互界面或者执行nmon -f -s 2 -c 5让它采集 10 秒后生成文件如果当前目录出现 nmon 开头的 .nmon 文件说明安装没有问题。2.2 ARM64AArch64环境下的编译与坑在 ARM64 机器上如果源里没有 nmon需要自己交叉编译。nmon 源码其实就一个 C 文件通常还需要一个编译脚本因为不同操作系统版本、不同内核版本需要定义不同的宏。编译前先确认内核版本号比如uname -r如果内核太新源码里读取 CPU 数量的函数可能需要打补丁否则会出现 CPU 数据全为 0 或者只显示 1 个核的怪问题。我踩过的坑是在 AArch64 小主机上直接拿了 x86 的 RPM 包强制安装结果是能装上但一跑就报错提示无法识别平台。正确的做法是找官方构建的 aarch64 版本或者用源码在目标机器上本地编译编译过程一般只需要 gcc 和 make。对于没有 gcc 的精简系统就提前在另一台环境相同的机器上编译好再拷贝过去前提是 glibc 版本兼容否则会提示找不到共享库。遇到这种情况用静态编译最省心gcc -static编出来的二进制几乎能在同架构任何发行版上运行我在嵌入式 Linux 上长期就是这么干的。2.3 基本运行模式与文件输出验证nmon 的运行模式大致分三类交互模式、采集模式、容量估算模式。交互模式直接敲 nmon 即可适合现场看采集模式靠 -f、-s、-c、-t 这些参数控制适合计划任务和夜间压测容量估算模式用 -x 或 -X可以在正式采集前预估 .nmon 文件会占多少磁盘空间。验证采集模式时我习惯这样写nmon -f -s 2 -c 10 -t -m /tmp/nmon_test命令含义是立即生成数据文件每 2 秒记录一次一共记录 10 次总共 20 秒-t 让数据里带上时间戳-m 指定输出目录。跑完后检查 /tmp/nmon_test 目录如果看到类似主机名_日期时间.nmon的文件并且用head查看能看到以 AAA、CPU001、MEM、NET 开头的行说明采集链路已经通了。3. 终端里的实时体检交互模式按键即战场3.1 最常用的几个按键和看数据的方式nmon 交互界面最初显示的是一个概览面板此时按不同按键顶部和下半部分会动态叠加对应的指标区再按一次就会隐藏。我实战中常用的是按 c显示 CPU 核心利用率可以看到每个逻辑核的 User%、Sys%、Wait%、Idle%还能看到整机平均值。按 m显示内存包括总内存、可用内存、缓存、页交换情况内存泄漏排查主要靠它。按 d显示磁盘能看到每块盘的读速率、写速率、busy 百分比这是定位磁盘瓶颈最快的入口。按 n显示网络按网卡分别展示收包、发包速率和错误包计数。按 t进入 Top Process 排行类似 top但可以直接看到每个进程占用的 CPU 和内存。按 k显示内核统计比如运行队列长度、上下文切换、swap 换入换出配合 CPU 的 Wait% 可以判断系统是否在跑 IO 重负载。按 j显示文件系统挂载点的使用率。读数据的顺序也有技巧。我通常先按 c 看 CPU如果 User% 高说明是业务计算密集如果 Wait% 高说明进程在等 IO如果 Sys% 高再看 k 里面的上下文切换次数通常能判断是不是锁竞争导致的内核开销。第二眼再看 d 的 DISK BUSY如果磁盘 busy 持续超过 70%基本可以断定 IO 侧有问题。最后用 n 看网络收发包判断流量是否异常。3.2 快捷键之外的小细节刷新间隔和颜色含义nmon 默认刷新间隔一般是 2 秒如果想让数据滚动更紧凑可以用交互模式启动参数指定比如nmon -s 1表示 1 秒刷新一次。拉高刷新频率适合压力测试时观察瞬时抖动但屏幕数据跳动太快反而不容易抓住规律我自己的习惯是压测场景用 1 秒平时巡检用 2 秒。颜色方面不同发行版终端里表现不完全一样但大体上绿色表示正常范围黄色接近警戒红色代表高风险。这块要注意不要在纯黑底终端和浅色终端之间对颜色作过度解读关键是看数值而不是看颜色。另外按 q 退出交互模式按 h 可以调出帮助页帮助页会列出当前版本支持的全部按键记不住按键的时候先按 h 比乱按强得多。交互模式下还有一个实用技巧把 nmon 放到 tmux 或 screen 会话里跑即使中途 SSH 断开重新连上后数据还在继续刷新。这个习惯帮我避免过好几次“人在现场等数据、网络一抖全白看”的尴尬。4. 无人值守采集参数套路与定时任务落地4.1 采集参数怎么组合才有意义采集模式的参数是 nmon 最有价值也最容易被用错的地方。核心参数就四个-f开启文件输出模式自动生成标准命名的输出文件。-s每次采样间隔单位是秒。-c一共采样多少次。-t在输出文件里记录每行的时间戳强烈建议加上不加的话后面做时间序列分析非常难受。组合逻辑很简单总采集时长 采样间隔 × 采样次数。比如我想要 5 分钟每 2 秒一个点的数据就是-s 2 -c 150想要 24 小时每 5 分钟一个点就是-s 300 -c 288。这里要特别提醒别把 -s 和 -c 写反。我见过有人写成-s 288 -c 300结果变成了 288 秒采一次、采 300 次总共跑了整整一天拿到数据后才发现采样密度完全不符合预期。除了这四个-m 用来指定输出目录避免把文件写到根分区-r 可以在文件头写入一个自定义标签比如-r 压测0701分析时更容易识别哪份数据对应哪场测试。如果希望每次采集完立即生成独立文件-f 本身就会把时间戳带进文件名不需要额外处理。4.2 定时采集与文件轮转的最佳实践生产环境不能总是手工登录去敲命令我一般用 crontab 在业务低峰期自动采集比如下面这个模板# 每15分钟采集一次每次持续10分钟每10秒一个点共60次 */15 * * * * /usr/bin/nmon -f -s 10 -c 60 -t -m /var/log/nmon如果是为了 7×24 小时长期留底更好的做法是每小时生成一个文件避免单个文件过大。比如# 每小时的第5分钟开始采集持续5分钟 5 * * * * /usr/bin/nmon -f -s 5 -c 60 -t -m /var/log/nmon/hourly这里要注意 crontab 用的解释器环境很干净建议写命令的绝对路径不要只写 nmon。同时确保 /var/log/nmon 目录存在且有写权限否则采集出来的文件是 0 字节。文件轮转同样重要。nmon 文件虽然不大但长期不清理也会占满磁盘。我习惯用 logrotate 管理 /var/log/nmon 目录保留 30 天即可。也就是配置 logrotate 规则把 .nmon 文件按天轮转、旧文件自动删除。就我观察以 5 分钟一个点、24 小时连续采集为例单文件大概几 MB30 天量级不会造成压力但不管不顾让它攒一年再小的文件也会积累成隐患。4.3 采集前如何估算文件大小并防止写爆磁盘nmon 官方给出了一个小工具参数 -x它可以进入“容量估算模式”根据当前系统里的 CPU 数量、磁盘数量、内存大小估算默认参数下产生的 .nmon 文件大小然后直接退出-X 则是乐观估算采用更小的平均值。实际使用时我建议在手工发起长时间采集前先跑一次nmon -x看看估算值再决定输出目录所在分区是否够用。另外需要注意如果系统磁盘数量特别多比如有几十块盘做 RAID 或者有大量 LVM 逻辑卷nmon 文件里每一行数据都会随之膨胀文件大小会比估算值大不少。所以宁可把输出目录放在一个独立的数据分区也不要放在根分区/下面否则采集数据写满根分区会导致系统服务写日志失败那是非常低级但非常致命的失误。5. 数据不吃灰nmon 出图的几种常用姿势5.1 用 Excel 模板批量生成可视化图表nmon 采集出来的 .nmon 文件本质上是个文本文件直接用 vim 或 less 看很不直观所以业内最经典的做法是用 IBM 退出的 nmon analyser Excel 模板来出图。这套模板是一个带宏的 Excel 工作簿打开后启用宏点击界面上的 Analyse nmon data 按钮选择 .nmon 文件它就会自动生成包含 CPU、内存、磁盘、网络、TOP 进程等几十张图表的工作表。我在压测报告中长期用这个方案理由是它不需要安装额外软件只要有 Excel 就能出图而且图表格式、配色非常整齐。需要注意的点有两个一是启用宏时 Excel 的安全性设置要放开否则没法运行二是文件里如果包含大量磁盘数据分析过程会偏慢内存小的机器容易卡住。如果是在 WPS 里用部分版本对 VBA 宏的支持不完整出图可能失败建议还是用正版 Excel 或者直接用下面的开源替代。5.2 nmonchart 与 nmon2rrd适合 Linux 服务器的自主分析如果不想依赖 Excel可以在服务器上直接用 nmonchart这个工具由 IBM 开发者发布作用是把 .nmon 文件转换成 SVG 格式的图表再用浏览器打开。还有 nmon2rrd它把 nmon 数据灌进 RRDtool 的轮询数据库适合自己搭一个轻量趋势展示页。我的实践经验是单机看报告用 nmonchart 最省事命令大概是这样nmonchart 主机名_20250701.nmon 报告.html生成的 HTML 里已经内嵌了图表直接下载到本地用浏览器打开就能看不需要服务器额外装 Web 服务。如果要在多台机器之间汇总对比可以先把多个 .nmon 文件弄到一台机器上分别转换再拼成一份汇总文档。不过这些工具在普通发行版仓库里不一定有常用做法是从官方渠道下载脚本然后根据本机环境手动配置依赖。5.3 不借助工具用 Python 和 awk 快速提取关键指标有时候我只想要某一时间段的 CPU 平均值或者抽查某个瞬间的磁盘读写情况用 Excel 模板反而慢。这种场景我直接写脚本解析 .nmon 文件。.nmon 文件每一行都有明确的节标识比如 CPU_ALL 行代表整机 CPU 数据MEM 行代表内存数据NET 行代表网络数据。下面这个 Python 脚本可以粗略提取 CPU 整机数据import sys def parse_cpu_all(path): rows [] with open(path, r, errorsignore) as fh: for line in fh: line line.strip() if line.startswith(CPU_ALL,): parts line.split(,) rows.append(parts) return rows if __name__ __main__: for row in parse_cpu_all(sys.argv[1]): print(row[1], row[2], row[3], row[4])这只是示例实际分析时需要结合文件头的时间字段把每一行的采样时间和指标对应起来再计算均值、峰值。用 awk 也能达到同样的效果而且不需要装 Python 环境awk -F, /^CPU_ALL/{print $2, $3, $4} 主机名_20250701.nmon这里我刻意没有给每个字段命名因为不同 nmon 版本的字段位置略有差异自己拿到数据后先 head 看一行确认再处理比照搬网上解析脚本更可靠。这个习惯值得多说一句任何监控数据的二次分析第一步永远是用 head 看原始结构而不是直接套公式。6. 实战排障场景与避坑清单6.1 一次 CPU 飚高排查现场怎么一步步找到真凶有一回线上服务突然变慢我登录服务器后先用top看到 CPU 使用率很高但一时说不清是业务进程还是内核在做冤大头。这时候我敲了nmon -s 1进入交互模式后同时按 c、k、t 三个键。第一眼看 c 面板发现 User% 稳定在 70% 以上Sys% 只有 6%这说明主要消耗在用户态业务进程上基本排除了内核 bug 和上下文切换失控。再按 t 看进程排行榜果然有个 Java 进程的 CPU 使用率接近 400%对应 4 个逻辑核。到这里还不能直接断定是这个进程的问题因为 Java 进程的 GC 线程也会表现为高 CPU。我接着按 k 看内核统计发现上下文切换数值不算离谱磁盘 Wait% 也不高说明不是锁竞争也不是 IO 等待大概率是真正的计算密集或者 GC 循环。这样一层层收窄整个排查过程不到两分钟。排查结束后我没有直接杀掉进程而是用采集模式留了一份证据nmon -f -s 1 -c 60 -t -m /var/log/nmon/case_20250701这份数据后来配合 nmon analyser 生成了 CPU 和 GC 相关图表用来和开发团队对齐。事后复盘时我觉得 nmon 最有价值的不是单看某个指标而是它让 CPU、进程、内核三块数据无缝联动起来这比一个个命令来回切换高效得多。6.2 内存泄漏与磁盘 IO 瓶颈分别怎么看内存泄漏类的故障nmon 的 m 面板最有说服力。重点不是看内存总数而是看 Used 是否会随着时间不断爬升同时 Buffer/Cache 不降。我习惯先用交互模式盯 5 分钟如果 Used 匀速上涨而业务流量没有同步变化基本可以判断存在泄漏。为了留下证据再用采集模式每 5 秒一个点连续采集半小时拿到 Excel 模板里看 Used 的趋势曲线比口头汇报有说服力得多。磁盘 IO 瓶颈的识别要区分两种场景。如果 CPU 面板里 Wait% 高、磁盘面板里 DISKBUSY 也高说明业务进程在等磁盘完成读写瓶颈确实在 IO 侧如果 DISKBUSY 不高但 Wait% 依然很高就要怀疑是不是进程数太多导致等待队列偏长也就是 CPU 调度的问题而不是盘的问题。这个区分很关键因为前者加磁盘就能解决后者削进程并发或者优化锁更有效。我在压测环境里见过一个误区只盯着磁盘的读写吞吐忽略了磁盘 busy 时间。实际上对机械盘来讲busy 百分比比吞吐量更能反映饱和程度因为小块随机读的吞吐可能很低但盘已经忙得喘不过气了。nmon 的 d 面板里重点看 busy 列这块经验在实际排障中屡试不爽。6.3 高频问题速查从命令找不到到文件时间乱了我按出现频率整理了一份 nmon 常见问题清单基本都是我这些年自己被坑过或者在社区里反复看到的问题。现象常见原因解决办法敲 nmon 提示 command not found包没装或 PATH 不包含安装目录用发行版包管理器安装或用绝对路径 /usr/local/bin/nmon采集文件是 0 字节输出目录不存在、没有写权限、磁盘满先手动创建目录检查 du -sh 当前分区剩余空间看不到 CPU 数据或只看到 1 个核内核过新与旧版 nmon 不兼容升级 nmon 版本或源码重新编译.nmon 里的时间超过 24 小时还在涨采集时间超过一天时间字段变成累加值每次采集不超过 24 小时跨天任务拆成多个文件磁盘很多文件膨胀快DISK 行数据量随磁盘数量增长提前用 -x 估算大小输出目录放到独立分区容器里采集数据缺项容器 /proc 受限看不到宿主机全部设备尽量在宿主机层面采集容器内数据仅作参考这里面最容易被忽略的是时间字段问题。因为 nmon 默认带一个从当天零点开始计算的时间戳如果采集超过 24 小时HH 部分会继续往后累加超过 23 也不会归零外部解析工具很容易误读。解决方案就是任务拆短或者用 -t 配合外部脚本记录真实开始时间后期分析时做偏移校正。我个人的习惯是单文件采集时长控制在一小时以内再通过 crontab 去轮转这样数据文件小、解析方便、时间也不乱。另外一个很细节但实用的建议给计划任务里的 nmon 加-r 标签比如-r web压测或-r 0701故障后期把几十台机器的数据混在一起时能一眼认出每个文件对应的场景不用再去翻系统日志。这个习惯在看大促压测数据时帮了我大忙。6.4 采集输出与后续处理的三个独家技巧最后分享几个比较零散但非常实用的细节。第一个技巧是采集时加上-I参数nmon 会把每个进程的累计 CPU 使用情况记录到文件中。默认情况下nmon 在采集模式里对进程数据的采样频率和 CPU 面板不同加了-I之后后续能用 Excel 模板或者脚本把进程排行拉出来特别适合复盘“哪个进程在什么时间段突然吃满 CPU”。不过代价是文件体积会明显增大不是每场采集都有必要开。第二个技巧是利用-^参数限制交互模式显示的 CPU 核心数。当服务器是 32 核、64 核时交互界面一屏根本看不完数据会滚动得非常快。用-^ 16可以只显示前 16 个核心的数据避免重要数值被挤出屏幕。数据文件里仍然保留全部核心的数据不用担心影响后期分析。第三个技巧是尽量保持同一批服务器上的 nmon 版本一致。因为不同版本的 .nmon 文件字段格式会略有差异如果混用多个版本Excel 模板解析起来可能出现列错位脚本分析更是容易出错。我一般会在巡检脚本里固定 nmon 版本升级前先在测试机验证一次确认生成的文件能被现有分析流程正常读取再批量下发。听起来很保守但在大规模服务器环境里这比用最新版本带来的收益要确定得多。在实际操作中我还有一个体会nmon 适合快速取证但不适合替代完整的监控系统。如果你需要的是长期历史趋势、告警通知、多机聚合那还得靠 Prometheus、Zabbix 这类平台。nmon 的价值在于它用最小的成本和最短的时间把一台机器当前的真实健康状态说清楚在应急和压测这两个场景里几乎没有对手。平时养成随手开采集的习惯真出故障时手里有数据分析起来才有底气。