
服务器凌晨2点40分告警群突然弹出一条消息某业务节点load average连续15分钟超过8。大半夜爬起来看监控面板CPU使用率明明只有60%内存也没满磁盘I/O看着还正常但load就是降不下来。这种场景干过运维的都懂——监控指标永远不是缺数据而是数据太多了关键是你得知道哪些数据能信、哪些数据该怎么组合着看。这篇东西就是把我在Linux系统指标监控这条路上踩过的坑、总结过的判断逻辑、沉淀下来的排查套路一次性梳理清楚。适合刚接手Linux运维的初学者也适合那些已经有两年左右经验、但每次出问题还是靠猜的同行。看完你能搞明白三件事指标背后到底是什么、哪些指标组合起来才能还原真实故障、以及遇到异常时用什么顺序去查才不白忙活。1. 监控的本质读懂内核给你留下的“体检报告”很多人用top看CPU、用free看内存用坏了也没想过一个问题这些数字到底从哪来的搞懂这一点后面所有的排查思路都会顺很多。1.1 一切指标都来自两个虚拟文件系统Linux里有个说法叫“一切皆文件”系统指标也一样。你敲top看到的那些数据本质上都是内核实时把系统状态写入/proc和/sys这两个虚拟文件系统里然后再由工具去读取、计算、格式化展示给你。举几个最常用的/proc/statCPU总使用率、各核使用率、上下文切换次数、开机时间全在这里。/proc/meminfo内存总量、空闲量、缓存量、Swap用量free命令显示的原始数据源。/proc/loadavg1分钟、5分钟、15分钟的负载均值load average三兄弟的老家。/proc/pid/status某个进程的内存占用、线程数、状态排查单进程问题时首查。/proc/diskstats每块磁盘的读写次数、读写扇区数、I/O耗时iostat的底层数据源。/sys/block/设备/stat新一代磁盘I/O统计接口很多新工具基于它。所以当监控数据出现异常时第一步永远不是怀疑工具而是直接看原始文件。比如top显示的CPU使用率和你预期不符那就cat /proc/stat算一遍比如内存明明显示还有几个G却触发OOM那就看/proc/meminfo里available和free的差值。技巧养成直接读/proc的习惯。监控工具可能因为采样间隔、计算方式、版本差异给你不同的数字但内核不会骗人。排查到后期所有争论最后都要回到原始文件上裁决。1.2 指标监控的正确打开方式看趋势别盯瞬时值我刚做运维那会儿服务器一告警就冲上去跑top盯着刷新那个瞬间的数字猜问题。后来被师傅骂了一顿才明白瞬时值只能告诉你“现在有异常”但告诉不了你“异常是从什么时候开始的”“持续了多久”“是在变好还是恶化”。而这些才是定位问题的关键线索。量化地说一次合格的故障排查至少要还原出异常前15分钟到异常出现后30分钟的指标曲线。没有历史数据的情况下你只能靠猜有趋势数据你可以直接看拐点。拐点对应的往往就是变更操作比如发布、扩容、配置修改。所以无论用商业监控平台、开源监控系统还是命令行工具一定要让数据有“时间维度”。单看top那一刻的值意义非常有限。2. CPU指标拆解load average与CPU使用率两个最容易混淆的指标CPU这块是运维面试和实操中最爱考、也最容易出误会的地方。核心就三个概念load average、CPU使用率、上下文切换。把它们彻底分开看CPU问题就解决了一半。2.1 load average到底算的是什么很多人把load average当成CPU使用率看这是最大的误区。load average在Linux里表示的是系统中处于可运行状态和不可中断睡眠状态的进程平均数。直白点说它不仅统计了正在用CPU的进程还把等待I/O的进程也算了进去。这就是为什么磁盘卡住、网络文件系统挂起时哪怕CPU闲着load也能飙升到几十。/proc/loadavg里的三个数字分别代表1分钟、5分钟、15分钟的平均负载。判断系统是否过载不能只看1分钟值要看15分钟值是否在持续上升以及三个值的相对关系1分钟 5分钟 15分钟负载正在上升需要关注。1分钟 5分钟 15分钟负载正在下降说明之前的压力已经在缓解。三个值都比较高且接近系统已经持续高负载运行属于稳态过载。至于多高算高不是拍脑袋定阈值而是拿CPU核数做参考load高于核数说明有进程在排队低于核数说明CPU资源尚有富余。一台4核机器load到8那排队情况已经很严重了一台64核机器load到8可能还在健康区间。2.2 从/proc/stat理解CPU时间片CPU使用率的计算逻辑比很多人想象中复杂因为Linux的CPU是分时复用的每个核在一秒内会交替执行用户态代码、内核态代码、处理中断、进入IO等待剩下的时间才闲着。看/proc/stat的前几行CPU那一行的数字从左到右分别对应user用户态时间、nice低优先级用户态时间、system内核态时间、idle空闲时间、iowaitIO等待时间、irq硬中断时间、softirq软中断时间、steal被虚拟机管理程序抢占的时间。top里的us、sy、wa、st就是这么来的us高用户态程序在密集计算比如Java应用跑满GC、Python脚本死循环、大量正则匹配。sy高内核态时间占比大多半是系统调用频繁常见于大量文件读写、网络收发、或进程频繁创建销毁。wa高CPU在等磁盘I/O返回这是磁盘性能瓶颈的典型信号但SSD时代要结合await细节看后面会单独说。st高虚拟化场景下宿主机在抢CPU资源云服务器上出现st走高往往是邻居VM在拼命。注意如果你用云服务器看到CPU使用率不高但业务很卡先查st。很多云厂商的监控面板看不到steal值得上机器敲top按数字1展开每个核的状态。2.3 上下文切换被忽视的CPU隐性杀手上下文切换cs可以理解为CPU在多个进程/线程之间来回切换的开销。切换本身不干任何实际工作纯粹是“换人的成本”。排查这个问题的完整链路是这样的先用top看整体cs值如果常年每秒几十万次一定有问题。用vmstat 1观察cs列同时看r运行队列和b阻塞进程判断切换是不是因为线程太多导致的。用pidstat -w 1定位到具体进程看哪个进程的cswch自愿上下文切换和nvcswch非自愿上下文切换在飙升。如果是nvcswch高说明进程在等待时间片CPU不够用如果是cswch高且伴随大量线程创建多半是编程层面的问题比如线程池无脑开线程、协程调度异常。我处理过最典型的一个案例某Java服务的线程数从200慢慢涨到8000上下文切换每秒上百万次但每个核的CPU使用率都不高。业务表现为接口响应越来越慢排查了半天根因是消息队列消费逻辑里一个锁等待导致线程大量阻塞阻塞线程又不断重试把CPU时间全耗在线程切换上了。3. 内存、磁盘与网络三个容易被误读的指标CPU只是性能问题的冰山一角。内存、磁盘、网络这三个模块的指标读法坑更多。3.1 free命令的正确用法available才是真正能用的内存看内存第一反应用free -h这一步没错但错就错在很多人盯着free这一列看。free列显示的是“完全空闲的物理内存”而Linux对内存的使用策略是“能用就绝不闲着”——空闲内存会被用来做文件缓存buff/cache下次读文件直接命中缓存能快好几个数量级。真正需要关注的是available这一列。它表示“在不触发Swap的情况下还能分配给新进程的内存量”包含了可回收的缓存部分。free低不是问题available长期为0才是问题。跟内存相关的常见误判有几个只看free不看available一台free只有200M但available还有8G的机器运行状态可能是完全健康的。Swap一用就慌Swap并非洪水猛兽少量使用说明内存吃紧但还能扛。真正要警惕的是Swap持续走高且伴随频繁的swap in/out用vmstat 1看si、so列这代表物理内存已经耗尽系统在靠磁盘硬撑性能会断崖式下跌。忽略内存的分配趋势用/proc/meminfo里的MemAvailable字段画趋势线比看任何监控面板的瞬时值都有用。排查内存问题还有一个利器ps aux --sort-rss | head -20按物理内存占用排序一分钟内就能找到内存大户。再进一步用pmap -x 进程号看某个进程内部各段内存的分布能定位到是堆内存还是栈内存还是映射文件撑爆的。3.2 磁盘I/OSSD时代iowait还可靠吗以前机械硬盘时代磁盘慢CPU等磁盘导致wa飙升这个指针很好用。现在SSD普及了磁盘快了很多iowait作为瓶颈信号的灵敏度也下降了——因为磁盘响应已经快到CPU基本等不到它。判断磁盘是不是瓶颈我现在的完整套路是三步iostat -x 1看每块盘的%util。这个值的含义是磁盘设备忙的时间占比理论上100%就是极限但注意SSD有并行处理能力util到100%不代表性能到顶要看实际的IOPS和带宽是否达到硬盘规格上限。看await平均I/O响应时间。机械盘await明显超过20ms就有问题了SSD应该稳定在个位数毫秒。如果await高但util不高说明单个I/O处理慢可能是磁盘硬件开始老化或队列配置不当。用iotop看具体是哪些进程在产生I/O。很多时候磁盘慢不是磁盘本身的问题而是某个进程在做全表扫描、日志疯狂输出或者备份任务在抢占带宽。这里有一个近些年SSD时代很值得注意的现象util和await都说正常但业务还是慢。这时候要看的是I/O的“并发度”也就是队列深度iostat -x里的avgqu-sz。低并发下延迟正常、高并发下延迟飙升这种情况通常要检查文件系统挂载参数、块设备调度算法比如mq-deadline和none的选择而不是一味加硬件。3.3 网络指标丢包、重传率与软中断网络层面的监控容易被两个盲区坑到。第一个盲区是只盯带宽使用率不看丢包和重传。带宽跑满说明吞吐需求大但丢包率上升往往是网卡缓冲区不够或者防火墙规则拦截TCP重传率上升则直接意味着网络质量在变差响应会莫名变慢。排查链路是ifconfig或ip -s link看每个网卡的RX/TX drop和error计数这两个值持续增长说明底层有丢包。netstat -s或ss -s看TCP层的重传、乱序、超时计数。抓包工具tcpdump对比抓一下重点看是否有大量重传包集中在某个连接上。第二个盲区是网络软中断。高流量场景下网卡收包会触发软中断softirq如果软中断都挤在某个CPU核上处理会出现“一个核跑满、其他核闲着”的奇葩景象。排查命令是top里按1看每个核的使用率再用cat /proc/interrupts看中断在各个核上的分布。发现问题后用irqbalance服务或者手动设置中断亲和性echo二进制掩码到/smp_affinity把中断分散到多个核上。顺带说一个运维里很容易被忽略的小点多块网卡绑定时如果驱动不带RSSReceive Side Scaling多队列功能单队列网卡在高PPS场景下天然会软中断集中。这是硬件选型问题监控指标只能暴露改不了。4. 一次完整故障排查从收到告警到定位根因的实操链路光讲指标不串一遍实战等于纸上谈兵。我拿最近处理的一个案例走一遍完整的排查流程这个案例很有代表性——初步看起来像CPU问题实际根子在磁盘而且中间还踩了个监控数据滞后的坑。4.1 告警与第一波基础检查某天下午3点监控提示一台数据库从库负载异常load average 15分钟值从0.5涨到6而且还在缓步上升。CPU使用率只有40%内存正常。我第一反应是查最近的变更记录——结果没有发布、没有配置变更、没有备份任务在跑。这本身就说明了问题一个没有变更的系统突然负载升高说明外部流量变了或者内部某个隐藏任务被触发了。基础排查命令走一遍uptime # 确认负载趋势 top # 看CPU/内存瞬时状态按1看每核 vmstat 1 5 # 看r、b、cs、si、so、wa的变化趋势 iostat -x 1 5 # 看磁盘util、await、avgqu-sz free -h # 看内存水位结果有个发现很关键iostat里sda这块盘的util只有15%看起来完全正常但avgqu-sz达到了12——队列深度非常高说明有大量请求在排队只是盘本身处理能力还在。这就是典型的“util正常、队列异常”瞬时数据差点把我带偏。4.2 用历史数据还原拐点这就是为什么我在第1节强调趋势数据的重要性。我直接调出sysstat采集的历史数据sar命令看前一个小时的数据sar -q -f /var/log/sa/sa$(date %d) | head -50 # 历史负载 sar -b -f /var/log/sa/sa$(date %d) | head -50 # 历史磁盘队列 sar -d -f /var/log/sa/sa$(date %d) | head -50 # 历史磁盘块设备数据出来之后真相就清楚了磁盘队列从下午2点40分开始异常而load是在2点50分开始爬升的——队列异常比负载异常提前了10分钟。这说明问题源头是I/O不是CPU。至于15:00的告警那已经是整个链条走完后的结果了。经验监控系统的告警永远滞后于问题的真正起点。所以排查时一定要回看历史数据找“最早偏离正常值的那个时间点”而不是从告警时间开始查。告警时间只是阈值被击穿的时间。4.3 定位到具体进程与内核行为确认是磁盘队列问题后接下来就得找谁在发I/O。iotop排第一的是一个之前没见过的进程PID是23085I/O读写一直在百分之三四十徘徊。ps一看是某个数据分析团队临时跑的一个Python脚本在持续扫一张大表并写临时文件。按理说下一步是直接kill掉并找团队负责人确认。但为了定位更彻底我用pidstat看了下这个进程的行为细节pidstat -d 1 5 -p 23085 # 按进程看I/O统计 pidstat -w 1 5 -p 23085 # 看这个进程的上下文切换结果发现这个进程不光在做I/O还在频繁创建临时文件——读一大块、写一个临时文件、再删掉循环往复。这带来的后果是文件系统元数据操作暴增元数据操作又要反复读写日志块设备最终把整个块设备的请求队列给挤满了。这也是为什么有时候单看某个进程的I/O量不大但整个系统却I/O拥塞——因为元数据操作的开销是隐性的不体现在按字节计量的I/O吞吐里却实打实占用了队列深度。4.4 处理与复盘清单处理方式不复杂和团队确认脚本不是线上任务后kill掉进程观察10分钟负载回落到0.3队列恢复正常。这个案子的复盘清单值得记录下来监控告警阈值只能作为触发条件不能作为故障起点的依据。util指标正常不代表磁盘健康必须结合队列深度、await和进程级I/O行为综合判断。临时任务一定要纳入进程管理不能直接在业务机器上裸跑脚本。系统的变化有三个来源变更、流量、隐藏任务。排查时按这个顺序排除能少走很多弯路。5. 从命令到监控体系手工排查之外的工具链搭建手工排查能力是基本功但生产环境不可能靠人肉盯top。这套监控体系怎么搭、工具怎么选决定了你的运维是“救火型”还是“预防型”。5.1 采集层sysstat是永远逃不开的基础无论用不用开源监控系统每台Linux机器都应该装sysstat。它就是sar、iostat、mpstat、pidstat这些命令的集合包而且自带cron定时采集把历史数据落到/var/log/sa/目录默认保留一个月。装好sysstat之后有件事必须做确认采集周期。默认配置是每10分钟采一次这个粒度对故障复盘来说太稀了。我习惯把周期调到每2分钟一次历史保留60天。做法是改/etc/cron.d/sysstat里的调用参数以及/etc/sysstat/sysstat中的HISTORY变量。有历史数据之后日常运维就有了“先问过去再看现在”的底气。半夜被叫起来的时候第一件事永远是跑sar -q -f /var/log/sa/sa昨天的日期看昨天的指标是否已经出现偏离经常能省下大把时间。5.2 实时层atop和htop两个值得常驻的工具实时排查场景我推荐两个比top好用得多的工具atop和htop各自有独特的优势。atop最厉害的地方是全量采样——它记录每秒钟每个进程的CPU、内存、磁盘、网络数据并且可以按时间轴回放。相当于系统自带了一个“行车记录仪”故障发生后还能倒回去看故障期间每个进程到底干了什么。这个能力在追查那种“幽灵负载”问题时价值极高。htop强在交互体验和多核展示。按F5能看到进程树按H能看到线程按M按内存排序、按P按CPU排序比top原生体验好太多。作为日常巡检的第一落点htop能让你用最短时间建立起对系统整体状态的感知。5.3 开源监控系统选型核心是采集口径与告警能力监控系统的选型比较说到底不是比功能列表长短而是比三个维度采集口径是否灵活、告警规则是否能自定义复杂逻辑、故障发生时能否快速定位指标曲线。维度Prometheus GrafanaZabbix云厂商自带监控采集方式拉模式客户端暴露指标接口推模式agent主动上报agent上报指标灵活度高可自定义Exporter采集任何数据中模板为主低预设指标项告警能力基于PromQL的复杂告警规则触发器表达式强大简单阈值适合基础场景历史数据默认本地存储可对接远端存储数据库存储清理麻烦一般保留数天到数十天上手成本中高需要理解指标模型低模板一键导入零成本以我在生产环境的经验来看Prometheus阵营目前是主流方向核心原因是它的指标模型和Kubernetes天然契合Exporter生态也很丰富——node_exporter就能覆盖绝大多数系统指标Redis、MySQL、Nginx这些中间件也都有对应的Exporter。但有一个坑必须提醒任何监控系统都要先验证采集数据的准确性。我踩过的例子是node_exporter的磁盘指标和iostat的数值大概率存在偏差因为两者对I/O统计的口径不完全一致如果告警规则直接基于Prometheus的数值设置可能出现磁盘明明已经很慢了但告警没触发的情况。实践中的做法是双轨验证新装监控系统后手动用iostat、free、top对比连续采样一周确认数据一致性然后再设置告警阈值。这一步不能省。5.4 告警设计不是越灵敏越好而是要减少“无意义告警”告警这块我见过的极端案例是有人把告警阈值设置得极其激进结果一天收几百条通知最后团队集体屏蔽告警群——这比没有监控还危险。合理的告警设计原则有三条告警要反映业务风险而非指标波动。CPU偶尔飙到90%只要1分钟就回落不值得打扰人持续15分钟高于80%才需要关注。所以告警规则必须有持续时间条件不能只看瞬时值。告警必须附带上下文信息。一条合格的告警应该包含异常指标当前值、正常基线的参考值、异常开始时间、相关进程或设备的定位信息。没有上下文的告警收到的人也不知道该干什么。告警要有分层和升级机制。P0级核心业务不可用直接打电话P1级资源逼近瓶颈发即时消息P2级趋势性风险进日报汇总。该用电话通知的不要用群消息该用日报沉淀的不要半夜震铃。6. 长期维护中的经验补遗时间同步、日志关联与自省讲完主线的监控方法还有几个边角料环节看着小实际在生产环境里经常绊人一跤。6.1 时间同步所有监控数据的“隐形地基”监控系统里所有数据都带时间戳故障复盘更是依赖时间轴对齐。如果服务器时间不准轻则日志和监控对不上号重则分布式环境下事件顺序完全错乱。所以时间同步这件事应该被当作监控体系的一部分来维护。检查方法很简单timedatectl status # 查看时间同步状态 chronyc sources -v # chrony环境下查看同步源状态 ntpq -p # 老版ntp环境下查看同步源状态注意用ntpdate做一次性校时的服务器时间会跳变跳变期间如果正好在发日志和监控数据时间戳会对不齐。推荐用chrony做渐进式校时通过调整时钟频率让时间慢慢对齐而不是瞬间跳变。生产服务器全部配置好ntp并且开启定期校验这个动作要写进服务器初始化清单里不能靠人肉一台一台检查。6.2 日志指标联动监控数字背后是具体事件指标监控只能告诉你“系统变成了什么样”日志分析才能告诉你“为什么变成这样”。实战中最高效的配合方式就是指标异常时立即把对应时间窗的日志拉出来关联。系统日志方面关注/var/log/messages下是否有内核报错、OOM记录、磁盘I/O错误应用日志方面用journalctl --since和--until按时间窗过滤重点看错误堆栈点和指标拐点的对应关系。日常大家可以有意识地训练这个习惯每次处理完一个故障反问自己如果下次只看指标曲线能不能猜出问题类型逐步做到看到磁盘util上升就自动联想到去看哪几个日志文件形成肌肉记忆效率会高很多。6.3 监控自身的成本与盲区监控也要有成本意识。我在生产环境见过node_exporter部署过量导致指标采集本身消耗了可观I/O的情况也见过把日志采集到Elasticsearch再查监控指标这种重方案把运维复杂度推高数倍的配置。指标采集密度不是越密越好2秒一个点对绝大多数场景都够用默认配置往往才是性价比最优解。还有一个盲区是很多监控系统默认不覆盖的指标比如进程级别的线程数、文件描述符数量fd、TCP连接状态分布。这些指标对排查实际问题非常关键却经常在监控面板上看不到。建议至少在每台机器上配好ss -s的定期采样、进程fd数的监控告警。别小看fd数——很多“连接数过多”“莫名无法创建新连接”的故障根因都是某个进程把文件描述符耗尽。最后再分享一点监控这套东西工具永远在演进今天讲的具体命令和参数可能过两年就有替代品但底层思维不会变先理解内核暴露了哪些数据再想清楚这些数据组合起来能说明什么问题最后形成自己的排查路径。如果你刚入行在把监控平台建好之前先把20个最常用的指标命令敲熟能解释清楚每个字段的含义和数据来源。有了这个基础后面不管接触什么监控系统、什么新工具都能很快看穿它背后的逻辑。我个人习惯是每隔一段时间就会翻一翻手头机器的/proc/stat和/proc/meminfo对照监控面板验证数字是否一致。这么做看起来有点笨但恰恰是这种“笨功夫”帮我在多次故障中第一个发现问题所在。监控能力没有捷径把基本功练扎实比安装再多花哨的工具都管用。