
接手过服务器运维的人都有过这种体验服务明明在跑用户却反馈响应慢你跳上机器习惯性地敲出top、vmstat、free、df、iostat这批命令。这五个命令是Linux系统资源排查的基础top看CPU和进程、vmstat看整体压力和内存调度、free看内存水位、df看磁盘容量、iostat看磁盘IO。这篇文章我想把自己的实际心得完整讲一遍包括每个字段该怎么读、什么场景用哪个、怎么把命令组合起来定位问题以及我踩过的一些坑。刚入门的朋友可以直接按图索骥有经验的老手也可以当查漏补缺的参考。1. 先搞清楚一条命令到底在告诉我们什么1.1 系统资源的四个观察维度很多人排查问题习惯性拎着top命令就上盯两眼就下结论其实这样很容易被表面数字带偏。我建议在敲任何命令之前脑子里先建立一张简单的资源地图CPU、内存、磁盘、网络。这里面的“磁盘”还要再拆成容量和IO性能两层容量看还有多少空间可用IO性能看读写快不快。服务器响应变慢问题可能落在任何一个维度上也可能是几个维度叠加在一起比如内存不足导致swap频繁又引发磁盘IO升高。top、vmstat、free、df、iostat这五个命令正好对应这几个维度。top管全局一屏能看到CPU、内存和进程排行vmstat管系统整体压力和内存调度free专注内存剩余和缓存回收df只看文件系统容量和inodeiostat是磁盘IO的放大镜。把它们组合着用基本能覆盖日常排障九成以上的场景。我的习惯是先跑一轮全局命令判断是哪一类资源出了问题再拿着放大镜去深挖效率会高很多。1.2 单点命令的局限和交叉验证思路单独用任何一个命令都容易得出误导性结论。比如top显示CPU使用率才10%但服务就是访问很慢这时候你不看vmstat的wa列可能就漏掉了磁盘IO卡顿的问题。再比如free显示used内存很高你要是不理解buff/cache可回收就很容易误判成内存泄漏。所以我平时有个固定习惯遇到性能问题先在脑子里过一遍“四维模型”然后按顺序把命令跑一遍像侦探一样做交叉验证。下面这个表是我平时给自己梳理的工具分工你也可以存一份排查的时候照着选工具就行。资源维度首选命令辅助命令重点关注CPU计算压力topvmstat、mpstatus、sy、负载、r列内存水位freetop、vmstatavailable、si/so、swap磁盘容量dfdu、lsofUse%、inode使用率磁盘IO性能iostatvmstat、topawait、%util、wa网络吞吐需要另装工具sar、nicstat本组命令不覆盖网络这里要补充一句这四个命令默认看的是瞬时状态或者从开机以来的平均值如果你需要长期趋势最好配合定时采样和监控系统。我自己在产环境里会用sysstat的sar保存历史数据故障发生之后能回放时间线把问题出现的起点和持续时间都画出来。后面讲到批处理用法时你可以把它直接接到采集脚本里长期积累下来就是一笔宝贵的基线数据。2. top一眼看全局的首选工具2.1 顶部信息区是怎么构成的top跑起来之后屏幕最上方是汇总区域我习惯把它拆成四块来讲。第一行是系统概况包括当前时间、开机运行时长、登录用户数还有load average。load average后面有三个数字分别是1分钟、5分钟、15分钟的平均负载。很多人问它到底代表什么简单说就是过去这段时间里处于“正在运行”或“等待运行”状态的进程平均数。注意它跟CPU使用率不是一回事一个负载很高的机器CPU使用率可能只有百分之几十因为进程可能在等IO。第二行是进程统计total是进程总数running是正在运行的sleeping是休眠stopped是停止zombie是僵尸。僵尸进程需要特别留意它不占CPU、不占内存但会占PID号如果数量持续增长而不消失多半是父进程没有正确处理子进程退出往往是程序bug的一种外部表现。第三行CPU状态是排查CPU问题时最常用的一行us是用户态占用sy是内核态占用ni是调整过优先级的进程占用id是空闲wa是IO等待hi是硬中断si是软中断st是被虚拟机管理程序偷走的时间主要在云主机上需要关注。判断CPU瓶颈我主要看ussy是不是接近100%以及wa是不是异常高。第四行和第五行是内存和交换分区。Mem那一行里total是物理内存总量free是完全空闲的内存used是已被使用的内存buff/cache是文件缓存。Swap行同样有total、used、free。另外还有一个avail Mem字段这个才是真正可用的内存值包含了可回收的缓存部分。我判断内存是否紧张第一眼看的其实是avail Mem而不是free这个细节在后面free命令的部分还会再展开。为了让这段输出更好认我贴一个简化版的示例实际跑出来结构类似这样top - 10:32:44 up 2 days, 4:21, 2 users, load average: 3.21, 2.80, 2.60 Tasks: 287 total, 3 running, 283 sleeping, 0 stopped, 1 zombie %Cpu(s): 35.2 us, 12.4 sy, 0.0 ni, 48.1 id, 2.6 wa, 0.0 hi, 0.7 si, 0.0 st MiB Mem : 15948.5 total, 4120.3 free, 7211.8 used, 4616.4 buff/cache MiB Swap: 8192.0 total, 7872.0 free, 320.0 used. 7291.5 avail Mem2.2 进程列表区和交互快捷键top下半部分是进程列表默认按CPU占用排序。需要关注的列有PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME、COMMAND。新手最容易困惑的是VIRT和RES。VIRT是虚拟内存大小包含了进程申请的地址空间即使没真正用到也会算进去所以一个进程VIRT显示几十G很常见RES是常驻物理内存也就是进程真正占用的物理内存。判断内存占用一定要看RES别被VIRT吓到。S列是进程状态R是运行S是睡眠D是不可中断睡眠Z是僵尸T是停止。D状态尤其值得注意它通常意味着进程阻塞在磁盘IO上比如网络存储延迟、磁盘故障等情况。交互模式下有几个快捷键非常实用P按CPU排序M按内存排序T按累计CPU时间排序1切换查看每个CPU核心的使用率q退出k可以杀掉指定PIDr调整进程优先级。排查Java进程或线程问题时可以用top -H查看线程列表再配合其他工具定位到具体线程。批处理模式则适合脚本采集top -bn1表示只采样一次适合在脚本里抓当前快照。生产环境采集CPU和内存数据时我不建议用top做长时间轮询它会增加额外开销但短期内手动排查完全没问题。3. vmstat和free内存与系统压力的双人组3.1 vmstat输出里的关键字段vmstat是排查系统整体压力时我必用的一条命令最常用的写法是vmstat 1 5表示每1秒采样一次一共采样5次。我第一次用的时候踩过一个坑第一行数据是从开机到现在的平均值不是当前状态所以如果你只跑一次vmstat看到的数据其实没有参考意义。正确做法是至少跑两三次从第二次开始看。输出字段里procs这行有两个关键列r列是运行队列中的进程数b列是阻塞在IO上的进程数。r值持续大于CPU核数的时候说明有进程在CPU上排队等执行b列持续非零常见于磁盘故障、网络存储过慢或者某块盘IO饱和。memory那行swpd是已使用的交换分区量free是空闲物理内存buff和cache是缓存。swap这行是整个输出里我最关注的地方si是每秒从swap读回内存的量so是每秒写入swap的量。这两个值如果长期不为0说明内存真的不够用了系统在频繁地换入换出应用响应会明显变慢。io这行的bi和bo是每秒从块设备读入和写出的量单位通常是KB。system行的in是每秒中断数cs是每秒上下文切换次数。上下文切换过高常见于线程过多或者应用频繁加锁。cpu行的us、sy、id、wa、st和top里的含义一致但vmstat胜在能看连续趋势比如us从30%慢慢涨到90%wa从5%涨到60%你就能直观感受到系统是在CPU计算上慢下来还是被磁盘拖住了。3.2 判断内存压力的正确姿势free命令简单到不能再简单但很多人会解读错。free -h输出里Mem行依次是total、used、free、shared、buff/cache、availableSwap行只有total、used、free。我平时判断内存压力的顺序是先看available再看swap使用最后配合vmstat看si/so趋势。为什么不能只看used因为Linux内核的内存策略是“有空闲就拿来当缓存”buff/cache会尽量做大所以used高不代表内存不够。真正不够的时候内核会自动从缓存里回收内存给应用。available这一列就是从系统角度看当前还有多少内存可以分配给新程序。如果你用的发行版free输出里没有available列可以用free加buff/cache粗略估算但更严谨的做法是升级到新版procps工具包。再补充一个实战经验swap使用量高不一定马上就是灾难。如果机器开了很久之前发生过一次内存峰值swap里留了些历史数据只要si/so不再持续发生通常可以继续观察。反过来即使swap使用量是0只要si/so频繁跳动同样说明内存吃紧。所以单看free某一时刻的输出不够要结合vmstat的趋势一起判断。顺便说一句free支持-s参数做定时刷新比如free -h -s 3适合盯着一块屏幕观察内存变化。排查内存泄漏时我习惯在日志里标记时间戳同时用free -s 10和vmstat 10记录一段时间的采样数据回来对比曲线能很快发现是哪一段引发了内存增长。4. df与iostat磁盘空间和IO的排查组合4.1 df用法与inode问题df是用来查磁盘容量的默认单位是KB看起来很不友好所以我一般直接用df -h以人类可读的方式显示再用df -T看文件系统类型。挂载在根目录的那一行Use%使用率到了85%以上我就会开始提高警惕真的到100%就麻烦了因为很多程序对磁盘写满的反应是直接崩溃连日志都来不及留下。这里必须单独提一个很容易被忽略的坑inode耗尽。df -i查的是inode使用率。小文件特别多的场景比如邮件队列、消息堆积、临时文件目录会出现明明磁盘还有几个G但文件就是创建不出来的情况报错通常是no space left on device。这种问题用df -h查不出来只有df -i能看到inode已经100%。我当年在这个坑上耗过大半天后来养成习惯每次看磁盘都同时跑df -h和df -i两个命令。df和du怎么配合使用也是常见问题。df是从文件系统层面看整体使用量du是从目录层面统计实际占用。比如某个分区df显示用了80G但你du一层层找下去目录加起来却没有80G这种情况往往是被删除但仍被进程占用的文件在作祟。定位方法是用lsof | grep deleted找到这些文件确认后重启相关进程或者清空文件句柄空间才会真正释放。这个坑在日志文件被rm但没有释放句柄的场景里特别常见。4.2 iostat输出里的IO指标iostat是查看磁盘IO最核心的命令。基本用法是iostat -x 1-x表示扩展模式1是采样间隔。如果你传了设备名可以只看某块盘比如iostat -x 1 sda。跟vmstat一样iostat第一次输出的数据是从开机累计到现在的平均值不能直接当成当前状态要看第二组及之后的采样。默认输出里avg-cpu部分和top差不多重点说设备部分。rrqm/s和wrqm/s是每秒合并的读、写请求数r/s和w/s是每秒实际发出的读、写请求数rkB/s和wkB/s是每秒读写的数据量。avgrq-sz是平均每次IO请求的大小avgqu-sz是平均请求队列长度。await、r_await、w_await是平均IO响应时间这个时间是包括了在队列里排队的时间。svctm是平均IO服务时间即设备真正处理一个请求的时间。判断磁盘是否成为瓶颈我建议综合看几个指标而不是只盯%util。%util表示设备处理IO请求的繁忙程度接近100%说明设备几乎一直在干活。但要注意SSD这类设备支持排队和并发%util为100%时响应时间可能依然很好此时要结合await、avgqu-sz来看。经验上机械盘的await持续超过几十毫秒多数情况是磁盘忙不过来的信号SSD的await通常在几毫秒内。另外如果svctm小于await很多说明请求大部分时间花在排队上典型表现就是请求太多、磁盘忙不过来。5. 实际排查案例从命令到结论5.1 案例一应用响应慢先看哪里假设你收到告警说某台应用服务器响应时间变长你SSH上去之后的第一条命令是什么我会先跑top -bn1只看一次采样。如果发现某个进程的%CPU已经到300%以上说明它在疯狂消耗CPU如果看到wa很高比如60%以上我会立刻跑vmstat 1 5确认再配合iostat -x 1找到对应磁盘。这就是前面说的定位流程先看全局再具体到块设备。我遇到过一种情况是top里CPU看起来不高wa也不高但load average到了20多。这个组合很奇怪继续跑vmstat才看到procs里的r列在20左右徘徊等于说有一大堆进程在排队等待CPU但CPU使用率却显示不高。后来发现是某个程序创建了大量线程每个线程都在忙等锁系统的上下文切换cs列每秒几万次。用top -H看到线程分布后配合日志定位到了代码里的锁竞争问题。这种问题靠单一命令根本没法解释必须多命令交叉印证排查思路才会顺。5.2 案例二磁盘空间告警但文件删不掉再分享一个磁盘相关的排查过程。当时df -h显示根分区Use%到了97%再df -i看inode正常。我先用du -sh /var/log/*逐个目录找大文件发现某个日志目录占了60多G。按常理这时候该清日志了但奇怪的是rm掉几个大的旧日志文件后df -h显示使用率一点没降。这种局面很典型大概率是某个进程还持有被删除文件的句柄。执行lsof | grep deleted果然看到有个进程的日志文件被标记为deleted但句柄没释放。处理方式不是直接kill进程而是先确认它对业务的影响允许后再重启进程。重启之后df -h立刻降下来一切正常。如果无法重启还有一种办法是用重定向清空文件内容比如: /proc/PID/fd/FD编号这样既不中断进程又释放空间。这个技巧在处理日志文件句柄被占用时非常有用建议记下来。整个过程用到的命令其实就那几条df、du、lsof、top但组合顺序很关键。5.3 案例三内存究竟够不够也有过被free输出吓到的时候。第一次看free -hMem行used到了12G多free只剩200多M第一反应是这机器内存是不是要爆了。但冷静下来仔细看buff/cache有3.5Gavail Mem还有4G多而且vmstat 1 5里si/so全是0swap用了300M但没有增长。这种状态说明内核对缓存的管理是健康的被占用的内存随时可以回收给应用完全可以继续跑不用贸然加内存或者重启服务。反过来如果avail持续下降si/so开始跳动swap使用量一路在涨那才是真正需要处理的时候。处理内存问题通常有几个方向先查有没有明显的内存泄漏再看是不是某些进程缓存设置过大最后才是考虑加内存。排查过程中我会用top -M按内存排序看进程排行再用ps aux --sort-rss辅助对比两条命令交叉看一下基本能锁定是哪个进程在吃内存。6. 常见问题与避坑心得6.1 输出解读最容易踩的坑现象常见误判正确做法load高、CPU使用率低以为CPU不够用vmstat看r列和wa列可能是IO阻塞或进程排队free显示free很小以为内存耗尽看available、si/so、swap趋势再下结论iostat %util接近100%认定磁盘瓶颈结合await、avgqu-sz、svctm判断是否真饱和df空间没满但创建文件报错以为是空间问题用df -i查inode使用率第一次vmstat/iostat输出异常直接当成当前状态忽略第一行平均值从第二次采样看第一个坑是load average的误读。很多监控图把load画得很重但load本质上包含了CPU队列和不可中断IO的进程机器慢在磁盘上时load一样会高。我见过有人因为load高就盲目加CPU结果完全没解决问题。第二个坑是free只看free列这一点前面反复强调过不再多说。第三个坑是%util它与设备并发能力强相关老机械盘和新型SSD的评判标准完全不同建议每次结合await一起看。还有一个环境层面的坑在容器里执行top看到的宿主机信息而不是容器自己的资源使用情况。容器内排查资源问题最好直接用cgroup的统计接口或者依赖容器编排平台提供的监控数据。如果你只是登录到物理机排查那top、vmstat看到的就是宿主机全局情况属于正常。另外不同版本的procps、sysstat输出格式会有差异比如字段顺序、单位显示跨版本对比时要留意别被微小的格式差异误导。6.2 我的实战经验总结给几个我长期实践下来的建议。第一命令组合优先我习惯的排查顺序是top确认大方向vmstat看趋势和系统压力free确认内存水位如果怀疑磁盘再上df和iostat。第二采样不能只采一次生产环境至少要观察1到2分钟的趋势特别是vmstat和iostat瞬间值和平均值都会骗人。第三采集数据要规范命令输出最好带上时间戳保存到文件或者直接对接监控平台。日常操作纪律上我提醒自己两条不要在内存紧张时凭直觉疯狂kill进程先确认进程对应的业务影响再说也不要一看到异常数字就急着优化先把多命令的数据拼出完整证据链。还有一点长期监控很重要临时敲命令解决的是当下问题历史基线和趋势数据能帮你提前发现隐患。如果你打算做数据采集脚本top可以用-bn1模式vmstat和iostat用固定间隔采样输出重定向到日志文件配合系统的定时任务就能自动积累数据。最后再说一个我自己的体会。这些命令看似基础但真正用好的关键是建立一套自己的排查思路。命令是你手里的工具真正值钱的是你脑子里那张资源地图和判断顺序。遇到问题先冷静定位再选对工具最后交叉验证得出可靠结论。希望这篇分享能帮你把Linux系统资源查看这件事彻底理顺下次服务器告警的时候少一点慌乱多一点底气。