服务端监控这件事做久了你会发现一个很拧巴的现实功能越全的工具部署和维护成本越高而真正在事故现场能救命的往往是那种“扔上去就能跑、跑完就能给出一份完整证据”的轻量工具。Nmon 就是这类工具里我用了最久的一个。它不依赖数据库不需要服务端和客户端配合一个几百 KB 的可执行文件拷到机器上一条命令就能把 CPU、内存、磁盘、网络、进程、文件系统这些指标按固定节奏记录下来产出一个后缀为.nmon的文本文件。事故过去了三天老板问“那天下午三点到底卡在哪”你把文件拖进分析表格里,几分钟就能画出一条完整的时间曲线。这篇内容面向的是需要在生产环境做性能取证、容量评估、故障复盘的运维和开发同学不管你是第一次听说 Nmon还是已经在用但只会敲nmon进交互界面看看下面这些关于采集参数、指标解读、开销控制和踩坑经验应该都能直接用上。1. 为什么这类老牌监控工具仍然值得放进工具箱1.1 从一次“说不清”的卡顿说起我经历过的最典型的一类场景是这样的业务方反馈某个时间段接口变慢但等运维同学登上去的时候系统已经恢复正常了top里一片祥和日志里也没有明显报错。这时候如果没有事前落盘的原始数据基本上就只能靠猜。有人会说“上监控平台啊”没错长期趋势和告警确实应该交给平台但平台通常有两个短板一是采集粒度粗一分钟一个点几秒钟的抖动全被平均掉了二是平台记录的是它关心的指标你事后想看某个维度的时候往往发现当初没开。Nmon 补的正是这个缺口。它的定位很明确——单机、高频、全量、离线留存。你让它每 10 秒采一次它就把那一刻 CPU 每个核的使用率、内存的 free/cached/swap、每块磁盘的读写次数和等待时间、每张网卡的收发字节和丢包、文件系统使用率和 inode、CPU 占用最高的若干进程全部写成一行行结构化的文本。这些文本不需要任何服务支撑直接打包带走在任何一台装了分析工具的机器上都能还原现场。我一般的做法是所有核心机器常驻一个 Nmon 采集任务间隔 60 秒保留 7 天遇到压测、上线、割接这种高风险窗口临时起一个 5 秒间隔的采集任务跑完就归档。这套组合的成本极低但关键时刻拿得出证据。1.2 它到底采集了哪些数据很多人以为 Nmon 就是“命令行版的 top”其实差别很大。交互模式确实像 top但真正有价值的是它的表格输出模式。在这种模式下它按固定格式把数据分段写入文件每一段有一个前缀标识常见的段包括CPU_ALL/CPU_P整体 CPU 使用率拆成用户态、系统态、等待、空闲以及每个逻辑核的明细MEM物理内存总量、空闲、缓存、缓冲以及 swap 的换入换出速率VM虚拟内存统计包括缺页、扫描、回收相关计数NET/NETPACKET每张网卡的字节速率、包速率、错误与丢包DISKBUSY/DISKREAD/DISKWRITE/DISKXFER/DISKSERV每块磁盘的繁忙度、读写吞吐、每秒 IO 次数、平均服务时间JFSFILE/JFSINODE每个挂载点的空间使用率和 inode 使用率TOP按 CPU 排序的进程快照带进程名、PID、CPU%、内存%SYS_SUMM系统概要包括负载、CPU 总数等这些分段的好处是“按需取用”。你做容量评估重点看DISKSERV和NET你查内存泄漏重点看MEM和TOP你定位 IO 抖动DISKBUSY加DISKSERV一起看基本能判断是磁盘扛不住还是应用发起的请求本身就是随机小 IO。注意TOP段是快照不是累计值。它只反映采样瞬间占用最高的那几个进程如果某个进程是“短促尖峰”型很可能被完全错过。这也是为什么高频采集在小窗口排查中不可替代。1.3 什么场景该用它什么场景别硬上用不用 Nmon我的判断标准很简单看三件事场景特征适合用 Nmon建议换别的方案单机性能取证、故障复盘非常适合原始的、高频的、完整的数据——容量规划、资源趋势评估适合采集一周数据做分布统计需要跨几十台机器做聚合看板时应交给集中式平台压测期间的资源画像非常适合5 到 10 秒粒度足够——秒级告警、自动止损不适合它没有告警能力用采集代理加告警规则容器化、弹性伸缩环境需要额外处理容器内视角不完整用 cgroup 指标为主的方案需要跨机上百年历史数据关联分析不适合文件是分散的落库后用查询引擎分析我在容器环境里的做法是采集跑在宿主机上容器内的应用指标另算。原因很实在容器里看到的/proc是做过隔离和映射的很多磁盘和网络指标读出来是宿主机的视角混在一起看容易得出错误结论。2. 部署之前必须先确认的三件事2.1 发行版差异与二进制兼容性Nmon 的安装方式有两种包管理器装和二进制直放。包管理器最省事主流发行版的仓库里基本都有apt、yum、dnf、zypper都能直接装。但这里有个坑仓库里的版本往往偏旧而不同版本支持的命令行参数不完全一样。我曾经在一个环境里按文档写了-T参数结果那个版本不认进程直接退出日志里只有一行用法提示排查了半天才发现是版本问题。所以我现在的习惯是装完第一件事先看版本和帮助nmon -V nmon -h 21 | head -60-h的输出里会列出当前版本实际支持的参数以它为准别照抄网上的文章。二进制直放适合那些不允许装包、或者仓库里根本没有的环境。做法是从可信渠道拿到对应架构的可执行文件放到/usr/local/bin下加执行权限。要注意两点一是架构必须匹配x86_64 的文件放到 ARM 机器上跑不起来二是动态库依赖用ldd看一眼确认libncurses之类的依赖在目标机上存在否则交互模式会起不来。静态编译的版本能省掉这个麻烦体积大一点但迁移性强我通常优先选它。# 直放后的基本检查 chmod 755 /usr/local/bin/nmon ldd /usr/local/bin/nmon /usr/local/bin/nmon -V2.2 采集文件的落盘位置与权限这一条特别容易被忽略。采集文件默认落在当前工作目录如果你从/root下敲的命令文件就在/root下如果从某个业务用户的 home 下敲文件就在那儿。等到要去找的时候往往已经忘了当初在哪敲的。我的规范是统一落在独立的采集目录比如/var/log/nmon/用-m参数指定。这个目录单独规划理由有三个。第一采集文件会持续增长放在系统盘上有把根分区写满的风险虽然单个文件不大但按天累积起来不容小觑第二独立目录方便做轮转清理一个find -mtime 7 -delete就搞定第三权限清晰只有采集用户能写其他人只读避免误删。用-m而不是靠cd还有个实际好处定时任务里的工作目录是不确定的靠cd切换很容易出问题-m显式指定就稳。mkdir -p /var/log/nmon chown nmon:nmon /var/log/nmon chmod 750 /var/log/nmon如果你的环境里不能新建用户那就用现有的低权限账号跑。不建议用 root 长期跑采集虽然读/proc需要一定权限但绝大多数指标普通用户就能读到只有极少数进程信息(比如其他用户的命令行参数)会受限。为了多读那几个字段而常年挂一个 root 进程不划算。2.3 时钟与时区事后对时的生命线这一条是血泪教训。有一次排查一个跨系统的调用超时我把 Nmon 的时间轴和应用日志的时间轴摆在一起怎么都对不上差了整整八个小时。最后发现是采集机时区没配跑的是 UTC而应用日志用的是本地时间。那半天时间全浪费在对时间上。所以部署采集任务之前务必确认timedatectl status date cat /etc/timezone 2/dev/null集群内所有机器必须统一时区并且开启时间同步。这件事平时看起来无关紧要出事的时候就是能不能把两条时间线对齐的关键。我现在会在采集脚本的开头顺手把当前时间和时区写进一个附属说明文件跟采集文件放在一起归档的时候一起打包以后谁拿到这份数据都不用再猜。3. 第一次跑通从交互界面到文件输出3.1 交互模式先摸一遍底虽然最终目标是自动化采集但我建议第一次上手还是先进交互界面走一圈。直接敲nmon就进去了界面是字符版的仪表盘。常用按键我整理成了下面这张表建议截图存一下按键作用使用场景cCPU 明细含每核看是否有单核打满m内存与 swap判断内存压力d磁盘繁忙度与吞吐定位 IO 瓶颈n网络接口速率排查带宽打满k内核统计看上下文切换、负载j文件系统使用率查磁盘写满t进程列表按 CPU 排序找热点进程.只显示繁忙的磁盘磁盘数量多时过滤h帮助忘了按键就看这个q退出——交互模式最大的价值是“手感”。你在这上面看一眼磁盘服务时间的量级、看一眼 CPU 等待占比再看文件的时候就知道哪些数字算正常、哪些算异常。这个基准感是纯看文档建立不起来的。3.2 一次最小可用的采集命令跑通交互模式之后就可以上命令行采集了。最小可用的一条命令长这样nmon -f -s 60 -c 1440 -m /var/log/nmon -t拆开解释一下每个参数的含义以及我为什么这么选-f表格输出模式。这是核心开关不开这个就只是交互界面。-s 60采样间隔 60 秒。常驻采集用 60 秒我认为是甜点值既能反映趋势文件又不会太大。-c 1440采样 1440 次。1440 × 60 秒 86400 秒 整整 24 小时。用次数而不是时长来算是 Nmon 的设计所以每次调整间隔都要重算次数这里很容易出错。-m /var/log/nmon输出目录。显式指定不依赖工作目录。-t记录 TOP 进程。没有这个参数事后你只能看到“CPU 高”不知道“谁在搞”。采完的文件名是自动生成的格式大致是主机名_年月日_时分.nmon。这个命名规则挺好天然带主机名和时间多机归档的时候不会打架。注意-c的含义是次数不是分钟数。我见过有人写-s 60 -c 60想要采一小时结果只采了 60 分钟——这个例子是对的但也有人写-s 10 -c 60以为是一小时实际只有 10 分钟。每次算一遍别凭印象。3.3 采集完成后的自检采集跑完别急着拿去分析先做三步自检。第一步确认文件非空且有完整头尾ls -lh /var/log/nmon/*.nmon head -5 /var/log/nmon/xxxx.nmon tail -3 /var/log/nmon/xxxx.nmon文件头会有几行以AAA开头的元信息记录程序名、版本、主机信息数据段前面会有ZZZZ开头的时间戳行标记每一个采样点。如果头尾都在说明采集完整。第二步确认采样点数量对得上。数一下时间戳行的数量应该和-c的值接近grep -c ^ZZZZ /var/log/nmon/xxxx.nmon如果数量明显少于设定值说明采集进程中途被杀了或者机器重启过。这种情况要在脚本里做补采或者告警。第三步确认关键段都在。至少要有 CPU、内存、磁盘、网络这四个cut -d, -f2 /var/log/nmon/xxxx.nmon | sort -u | head -40看一眼输出的段名列表缺哪个补哪个参数。这套自检我写成了一个小脚本每次采集结束自动跑一遍有问题直接发通知省得等到要用的时候才发现数据是残的。4. 命令行采集模式的完整拆解4.1 参数逐项过一遍别只会 -f -s -c只用-f -s -c能跑但会丢掉不少信息。下面这些参数是我实际会用到的按重要性排参数含义我的使用建议-f表格输出模式必开-s N采样间隔秒常驻 60专项排查 5 到 10-c N采样次数总时长 s × c每次重算-m DIR输出目录必开统一目录-t记录 TOP 进程必开否则事后不知道谁干的-T记录 TOP 进程并包含命令行参数排查时开能直接看到启动参数-d记录最繁忙的磁盘磁盘数量多时开聚焦热点-K磁盘吞吐以 KB/s 为单位数值小时开避免都是 0.0-N包含网络文件系统段有共享存储时开-J包含文件系统段关注磁盘写满时开-X包含文件系统容量与 inode与上一条配合-I不采集进程信息进程数量极大、开销敏感时用-g FILE自定义磁盘分组磁盘命名混乱、想按业务归类时用其中-T和-t的区别值得单独说一句-t只记录进程名-T会把完整的命令行参数也记下来。排查的时候差这一条有时候很关键比如你看到一堆同名的进程实例只有带上参数才能区分出是哪个业务在跑。-K这个小参数很多人不知道但它能救命。默认磁盘吞吐以 MB/s 为单位一块低速盘每秒几十 KB 的写入在文件里全是0.0你根本看不出有没有在写。加上-K之后变成 KB/s数字立刻有分辨力了。4.2 采集频率和文件体积的估算这是必须算的一笔账不然容易把盘写满或者把机器拖慢。我自己实测的经验值是这样的采样间隔单次采集时长单机文件体积约典型用途60 秒24 小时15 到 30 MB常驻留存30 秒24 小时30 到 60 MB重要机器的常驻10 秒2 小时8 到 15 MB压测、上线窗口5 秒30 分钟5 到 10 MB精细排查体积和三个因素相关采样点数、机器上的磁盘和网卡数量、是否开了进程段。磁盘多的机器DISK*段每行会很长体积翻倍很正常。所以上面的数字是大致量级别当精确值用你可以在自己的环境里跑一天看实际大小再定策略。按这个量级算一台机器保留 7 天占用在 100 到 200 MB 之间这个成本基本可以忽略。但如果机器有几十块盘、上百个挂载点就要重新评估了。4.3 定时采集与开机自启别用 crontab 硬拼最常见的做法是写 crontab每天定时起一个采集进程。这样能跑但有个明显问题采集进程会跨越零点。如果你设成每天 00:05 启动、采 24 小时那么实际覆盖的是 00:05 到次日 00:05中间有个几分钟的空档;如果设成每 24 小时重启一次又可能撞上正在采的进程。更麻烦的是机器重启后那一段数据就永久缺失了。我现在的做法是用一个常驻循环脚本采集完成之后自动开下一轮同时处理好文件名和清理#!/bin/bash # nmon_loop.sh - 常驻采集循环 OUT_DIR/var/log/nmon INTERVAL60 COUNT1440 KEEP_DAYS7 mkdir -p $OUT_DIR while true; do /usr/local/bin/nmon -f -s $INTERVAL -c $COUNT -m $OUT_DIR -t -K # 采集结束后清理过期文件 find $OUT_DIR -name *.nmon -type f -mtime $KEEP_DAYS -delete sleep 10 done配合 systemd 做守护比 crontab 靠谱得多# /etc/systemd/system/nmon-collect.service [Unit] DescriptionNmon collector loop Afternetwork.target [Service] Typesimple Usernmon ExecStart/usr/local/bin/nmon_loop.sh Restartalways RestartSec30 Nice10 IOSchedulingClassidle [Install] WantedBymulti-user.target这里有两个细节值得说。Restartalways保证进程挂了能自动拉起来RestartSec30避免疯狂重启。Nice10和IOSchedulingClassidle是给采集进程降优先级让它在系统繁忙时自动退让这一点在压测场景里很重要——你的监控工具不能成为被测系统的一部分。4.4 归档与轮转把数据管起来单个文件管好之后还要管整体。我的策略是三层第一层是本机留存保留 7 天用于即查即用。第二层是集中归档每天把前一天的采集文件同步到一个归档目录按月打包压缩。.nmon是纯文本压缩比很高通常能压到原体积的十分之一左右。第三层是异常快照一旦监控平台发出告警就自动触发一次高频采集比如 5 秒间隔跑 30 分钟单独存到事故目录里。这一层是真正体现价值的地方因为事后复盘要的就是那几分钟的细节。# 归档示例按月打包 ARCHIVE_DIR/data/nmon-archive/$(date %Y%m) mkdir -p $ARCHIVE_DIR tar -czf $ARCHIVE_DIR/nmon-$(date %Y%m%d).tar.gz /var/log/nmon/*.nmon归档这件事最忌讳“等要用的时候再找”。我在一次容量评估里需要三个月前的数据做同比结果发现早就被清理掉了只能从头开始重新采一个月。从那以后归档策略我就写进了标准交付里。5. 数据落盘之后如何把数字变成结论5.1 三种分析路径的取舍拿到.nmon文件之后有三条路可以走各有适用场景分析方式上手难度输出效果适合谁官方配套的表格分析工具低多张折线图直观一次性复盘、给非技术同学看文本命令行查看低原始数字无图快速确认某几个点自写脚本解析中可定制、可批量批量统计、定期报告表格分析工具是大多数人第一次接触的方式把.nmon文件拖进去自动生成十几张图表页。优点是零门槛缺点是文件大时打开慢而且它是交互式的没法塞进自动化流程。文本命令行适合快速确认。比如只看 CPUgrep ^CPU_ALL /var/log/nmon/xxxx.nmon | head -20输出是一行行的 CSV第一个字段是采样点编号后面依次是用户态、系统态、等待、空闲、CPU 核数。肉眼看几行就能判断有没有明显异常。自写脚本是我现在的主力方式。原因很简单我需要的是“结论”不是“图”。比如“这台机器在过去 7 天里CPU 用户态超过 80% 的时间占比是多少”、“磁盘服务时间的 95 分位是多少”这些问题用脚本几行代码就能回答而看图只能靠眼估。5.2 一个能直接用的解析脚本下面这个脚本我用了很久思路是先把文件读成结构化的行再按段分组最后算统计值。你可以直接拿去改成自己需要的指标。#!/usr/bin/env python3 import sys from collections import defaultdict def parse_nmon(path): 把 .nmon 文件解析成 {段名: [行数据列表]} sections defaultdict(list) with open(path, r, errorsignore) as f: for line in f: line line.strip() if not line or , not in line: continue parts line.split(,) head parts[0] # 数据段的格式通常是 BBBB,段名,... if head.startswith(BB) and len(parts) 1: name parts[1] sections[name].append(parts[2:]) elif head.isupper() and len(parts) 1: # 部分版本直接以段名开头如 CPU_ALL,... sections[head].append(parts[1:]) return sections def summarize_cpu(rows): 统计 CPU_ALL 段的均值与高分位 user, sys_, wait, idle [], [], [], [] for r in rows: try: # 字段顺序采样点, 用户%, 系统%, 等待%, 空闲%, 核数... vals [float(x) for x in r[1:5]] except (ValueError, IndexError): continue user.append(vals[0]); sys_.append(vals[1]) wait.append(vals[2]); idle.append(vals[3]) if not user: return None n len(user) user_sorted sorted(user) p95 user_sorted[int(n * 0.95) - 1] if n 1 else user_sorted[0] return { samples: n, user_avg: round(sum(user) / n, 2), sys_avg: round(sum(sys_) / n, 2), wait_avg: round(sum(wait) / n, 2), idle_avg: round(sum(idle) / n, 2), user_p95: round(p95, 2), user_max: round(max(user), 2), high_load_ratio: round( sum(1 for v in user if v 80) / n * 100, 2), } if __name__ __main__: data parse_nmon(sys.argv[1]) print(可用段:, , .join(sorted(data.keys()))) cpu summarize_cpu(data.get(CPU_ALL, [])) if cpu: for k, v in cpu.items(): print(f{k:16}: {v})跑出来的效果大致是这样可用段: CPU_ALL, CPU_P, DISKBUSY, DISKREAD, JFSFILE, MEM, NET, TOP samples: 1440 user_avg: 23.41 sys_avg: 6.18 wait_avg: 1.02 idle_avg: 69.39 user_p95: 61.77 user_max: 92.30 high_load_ratio: 3.61“95 分位”和“超过 80% 的时间占比”这两个数字比平均值有用得多。平均值会被大量空闲时间稀释你会觉得机器很闲但实际上每天下午有半小时是打满的。容量评估看的是峰值不是均值。注意不同版本 Nmon 的段前缀和数据列顺序略有差异,脚本里的字段位置要按你实际文件调。稳妥的做法是先head看几行确认列的含义再写死索引。5.3 关键指标怎么读阈值怎么定这是最需要经验的部分。同样一条曲线老手看一眼就知道有问题新手看不出所以然。我把常看的几个指标和判断逻辑列出来CPU 的“等待”比“占用”更值得关注。用户态高说明业务真在算系统态高说明系统调用多可能是频繁 IO 或者锁竞争等待高说明 CPU 在等磁盘这时候加 CPU 是浪费钱该查的是存储。我的一般判断是等待占比长期超过 5% 就要看一眼超过 10% 基本可以确认存在 IO 瓶颈。内存看的是趋势不是绝对值。空闲内存低不代表有问题缓存占满是很健康的。要看的是 swap 的换入换出速率只要这个值持续大于零说明物理内存真的不够了。另外看TOP段里的进程内存占比如果某个进程的内存曲线是单调上升、从不回落那大概率是泄漏。磁盘看服务时间不看繁忙度。繁忙度 100% 不代表有问题——现代存储队列深跑满很常见。真正要看的是平均服务时间机械盘超过 20 毫秒、固态盘超过 5 毫秒就需要警惕了。这个数字反映的是“一次 IO 要等多久”直接对应应用感知到的延迟。网络看的是错误和丢包不是带宽。带宽打满是一个渐进的过程能提前看到但错误和丢包是突发问题一旦出现就说明有链路或者配置问题。NETPACKET段里的 error 和 drop 计数只要在增长就得查。下面这张表是我自己用的阈值参考具体数字要结合业务基线调整指标关注阈值严重阈值说明CPU 等待占比 5% 15%指向 IO 瓶颈CPU 用户态 95 分位 70% 90%容量不足或热点代码可运行队列长度 2 倍核数 4 倍核数排队严重swap 换出速率持续 0持续增长内存不足磁盘服务时间 20 ms机械 50 ms存储响应慢磁盘队列长度 2 8请求堆积网卡丢包出现即关注持续增长链路或配置问题文件系统使用率 80% 90%有写满风险6. 几个真实场景的排查实录6.1 CPU 很高但进程列表里找不到元凶这是我遇到过最迷惑的一类问题。采集数据显示某个时段 CPU 用户态冲到 90% 以上但TOP段里所有进程的 CPU 占比加起来还不到 30%。第一次遇到的时候我怀疑是数据有问题后来才想明白几个可能。第一采样错位。TOP段记录的是采样瞬间的进程排名而 CPU 使用率是一个区间内的平均值。如果负载是短促脉冲式的两者天然对不上。这种情况要把采样间隔调小用 5 秒间隔重采一次。第二进程被合并统计。有些短生命周期进程频繁创建销毁在快照里根本抓不到但它们的 CPU 消耗实实在在发生了。这时候VM段里的进程创建相关计数会有明显升高可以作为佐证。第三虚拟化层的开销。如果是虚拟机宿主机层面的调度、中断处理会算在系统态里但不会体现为某个具体进程。这时候看系统态占比如果系统态明显偏高而进程列表干净基本可以往这个方向想。第四容器视角问题。采集跑在宿主机上进程列表可能被过滤掉了。这时候要确认采集时用的账号权限是否足够看到所有进程。排查顺序我一般是这样先确认采样间隔是否足够细再看系统态和用户态的比例最后看VM段的相关计数。三步走完大多数“找不到元凶”的情况都能有个方向。6.2 内存“被吃光了”其实什么事都没有这个坑新手几乎必踩。看到空闲内存只剩几百 MB第一反应是内存不够赶紧加内存或者重启服务。实际上 Linux 的内存管理策略是“能用就用”页缓存会把空闲内存占满这是设计如此不是故障。正确的看法是看三个数free、available、swap 使用。available才是应用真正能拿到的内存它等于空闲加上可回收的缓存。如果available还很充裕swap没有换出那就完全不用担心。真正要警惕的是这几种组合available持续下降同时swap开始换出 → 内存真的不够swap换入换出速率持续很高 → 已经开始影响性能了某个进程的常驻内存单调上升从不回落 → 大概率泄漏我踩过一次坑某服务的内存曲线一路向上我判断是泄漏准备安排重启。结果仔细看TOP段发现是缓存目录在涨因为业务在读大量小文件页缓存自然增长。等内存压力上来系统会自动回收。这件事让我记住一个原则在没搞清楚内存被谁占之前不要急着下“泄漏”的结论。6.3 磁盘 IO 抖动的定位思路有一类问题是“每隔十几分钟就卡一下”这种周期性抖动最烦人因为持续时间短肉眼抓不到。Nmon 的高频采集在这种场景下几乎是唯一手段。我的定位流程是三步第一步看DISKBUSY段确认抖动是集中在某一块盘还是所有盘。单盘抖动可能是那块盘的硬件或者 RAID 卡缓存策略问题全盘抖动更像是上层应用的一次批量操作。第二步看DISKSERV段确认服务时间的峰值。如果服务时间在抖动期间翻了好几倍说明是存储侧响应慢如果服务时间平稳但队列长度上升说明是请求量突增。第三步回到TOP段找时间点上对应的进程。把抖动的时间戳和进程快照对上经常能锁定是哪个定时任务在跑。有个细节很关键时间戳要对齐。ZZZZ行的采样时间是你唯一的对齐依据所有段的采样点编号是一一对应的。我一般会先写个小脚本把某个时间段的采样点编号提取出来然后只筛这个范围的数据看避免被大量无关数据干扰。# 提取指定时间段的采样点编号 grep ^ZZZZ xxx.nmon | grep 14:2[0-9] | cut -d, -f2拿到编号区间之后再按编号过滤其他段这样分析起来干净很多。7. 常见问题速查与开销控制经验7.1 问题速查表现象大概率原因处理方式交互界面打不开报终端相关错误缺少 ncurses 依赖或TERM设置异常装依赖或改用-f文件模式命令执行后立即退出无输出参数不被当前版本支持nmon -h看支持的参数采出的文件很小段不全参数缺失或进程被中途杀掉检查参数加进程守护文件名里的主机名是 localhost主机名未配置统一配置主机名便于归档识别磁盘吞吐全是 0.0单位是 MB/s数值太小加-K改为 KB/s时间轴和应用日志对不上时区不一致统一时区并开启时间同步采集进程占用明显间隔太短或进程数太多放宽间隔或加-I跳过进程段分析文件打开极慢文件过大、采样点过多缩短采集时长或先筛段再分析文件里的进程信息不全采集账号权限不足换有权限的账号或接受缺失7.2 采集本身的开销怎么压到最低监控工具拖慢业务是真实存在的风险尤其是采样间隔很短的时候。我做过几次对比影响主要来自三个地方进程段是最耗的。遍历/proc下所有进程的状态和命令行在进程数量上千的机器上开销不小。如果只关心系统级指标直接加-I关掉进程采集开销能降一大截。采样间隔是线性因素。5 秒一次和 60 秒一次开销差 12 倍。所以高频采集只用在短窗口不要长期挂着。写文件的量也要考虑。每次采样都会追加写入如果采集目录和业务数据在同一个盘上高频写入会干扰业务 IO。我的做法是把采集目录放到独立的盘上或者至少限制文件增长速度。另外就是前面提到的降优先级。Nice值和 IO 调度类的设置能让采集进程在系统繁忙时自动让路。这个配置看起来不起眼但在压测场景里有没有它差别很明显。注意任何采集工具都会有开销别相信“零影响”的说法。正确的心态是量化影响、控制影响而不是假设它不存在。上线前在预发环境跑一轮对比开采集和不开采集时的业务指标心里有个数。7.3 和集中式监控怎么配合我见过两种极端一种是什么都靠 Nmon机器上跑一堆采集脚本出问题还得手动捞文件另一种是全面上平台本地什么都不留结果平台一挂或者数据被覆盖彻底抓瞎。合理的分工是这样的集中式平台负责“面”也就是长期趋势、跨机对比、阈值告警、大屏展示。这些是它的强项一分钟一个点的粒度做趋势足够了。Nmon 负责“点”也就是单机的精细取证。当平台告警说某台机器异常时Nmon 的本地文件能提供秒级的细节这是平台给不了的。两者之间的连接点是告警触发的自动采集。我在告警规则里加了一个动作一旦某台机器触发高优先级告警就在那台机器上自动起一个 5 秒间隔、持续 30 分钟的采集任务。这样等你去排查的时候最关键的半小时数据已经完整落盘了。这个做法的成本几乎为零但省下的排查时间非常可观。这套组合我用了几年评价是平台让你知道“哪里可能有问题”Nmon 让你知道“到底发生了什么”。两者缺一不可但如果只能留一个我会留 Nmon因为它给的是原始证据而原始证据永远不会骗你。最后分享一个我自己坚持的小习惯每次处理完一次故障我会把当时用到的.nmon文件单独归档到一个“案例库”目录文件名加上一句简短描述比如“某服务IO抖动”“内存缓慢上涨”。时间长了这个库就成了我自己的基线参考。下次再遇到类似的曲线翻出历史案例一对比判断速度快很多。这件事花不了几分钟但积累下来的价值远超预期。