☰
通过top、vmstat、free、df、iostat组合定位Linux性能瓶颈
2026/10/20 18:54:59 网站建设 项目流程

1. 资源查看不是“跑几个命令”那么简单

Linux系统资源查看,top、vmstat、free、df、iostat这五个命令几乎是每本入门书里的标配。我见过很多人把每个命令背得滚瓜烂熟,但一遇到服务器告警,还是不知道从哪下手。原因是他们把这些命令当成了“查看工具”,而没当成“线索链”。实际上,这些命令组合起来就是一套系统性能诊断流程:CPU瓶颈看top、vmstat,内存瓶颈看free、vmstat,磁盘瓶颈看df、iostat。每个命令看到的只是一个切面,但切面之间是有联动的。

这篇文章适合刚接触Linux、或者已经会敲这几条命令但想更深入理解输出含义的人。我不会只给你讲参数,而是分享实际排查中怎么用、怎么解读、怎么从一行数字里找到问题根因。目标很简单:让你从“看到命令输出”变成“看懂系统状态”。

为什么把这几条命令放一起说?因为服务器卡成PPT时,你不可能只靠一条命令就知道原因。比如CPU高,到底是用户进程占用,还是内核在做IO等待?内存看起来吃紧,是真的不够还是有大量缓存可以回收?磁盘报告满了,但du找不到大文件,那多半是文件被删但仍被进程占用。这些问题,单看top或df都可能被骗,需要交叉验证。

我尽量把每个命令的“看什么”“忽略什么”讲清楚,带上实际数值示例。读完你至少能做到:拿到一台故障机器,按顺序执行这几条命令,几分钟内定位出大致瓶颈方向。当然,这套东西熟练之后,你会形成自己的排查习惯,不一定照搬我的顺序。

2. top:从进程列表到系统负载的实时监控

2.1 第一屏不是进程列表,是那五行的“总览”

很多人打开top,眼睛就直接盯住进程列表,找哪个进程CPU高。这没错,但容易漏掉更重要的信息。top默认输出前五行的系统概况,我已经养成习惯是先看这里,再决定要不要看进程表。

第一行显示系统当前时间、已运行时间、登录用户数和负载平均值。这里的load average有三个数值,分别代表过去1分钟、5分钟、15分钟的平均负载。注意,这个负载不是CPU使用率,而是处于可运行状态和不可中断睡眠状态的进程平均数量。一个粗略判断标准是,如果负载值接近或超过CPU核心数,说明系统有排队,可能已经过载。但要注意,如果是IO等待导致的不可中断进程,负载高但CPU可能并不忙。

第二行和第三行是进程总数和运行、休眠、停止、僵尸进程数量。我特别关注zombie,如果持续有僵尸进程,可能是父进程没有正确回收子进程。少量没问题,大量就别忽略。第四行、第五行是CPU状态和内存状态,CPU的us、sy、ni、id、wa、hi、si、st分别代表用户态、系统态、优先级调整、空闲、IO等待、硬中断、软中断、被偷取时间。us高通常是用户程序运算密集,sy高可能是系统调用频繁,wa高则说明CPU在等磁盘,st高多见于虚拟化环境被宿主机抢占。

2.2 交互按键是top的“隐藏效率”

进入top界面后,千万不要只用键盘上的上下键翻进程。我常用这几个按键:P按CPU使用率排序,M按内存排序,T按累计CPU时间排序。排查问题时,P是最常用的,能快速看到CPU占用前几名;但有时按T也有惊喜——某个进程瞬时CPU不高,但累计时间很长,说明它是一个持续消耗资源的老大难。数字键1可以展开每个CPU核心的使用情况,如果多核系统只有一个核接近100%,其他空闲,可能是单线程程序或中断绑定不均,和整体负载高是两回事。

k键可以直接发送信号给进程,r键可以调整进程优先级。不过我在生产环境几乎不用这两个键,生怕手抖输错PID。我更喜欢退出top后用命令行kill或renice,至少多确认一次。

2.3 top的局限:它只给你一个“瞬间”

top默认大约3秒刷新一次,进程列表每次变化都很快。就算某个进程平均CPU很高,你看到的瞬间值也可能只是50%或突然飙到100%。如果是间歇性消耗,top很难抓到规律。所以遇到CPU问题,我通常不会只靠top下结论,会配合top -bn1和vmstat的多点采样。

top -b是批处理模式,-n1表示只输出一次。这个输出没有交互界面,但内容和交互式的第一屏及进程列表完全一样。脚本或连续采样时很有用,比如每隔5秒执行一次top -bn1,把结果追加到文件,事后分析趋势。还可以用-p指定PID,只看某个进程,排查单进程资源占用时比全量输出容易读。

2.4 如何从top里区分“瞬时高”和“趋势高”

实际操作中,我会先看load average的15分钟值,如果这个值一直往上走,说明系统压力在累积,不是偶发现象;如果只是1分钟高、15分钟很低,可能只是刚刚有任务启动。CPU状态里的wa高,配合进程列表里D状态的进程,基本可以判断是IO瓶颈。进程列表里进程状态为R代表正在运行,S代表睡眠,D代表不可中断的磁盘等待。如果大量进程处于D状态,说明它们都在等IO,系统再空转也跑不快。这个逻辑比只盯CPU百分比准确得多。

3. vmstat:连续采样才能看准CPU、内存、IO趋势

3.1 先从命令格式说起

vmstat的经典用法是 vmstat 1 5,意思是每隔1秒取一次样,一共取5次。第一次输出比较特殊,它显示的是自开机以来的平均值,后续四次才是实时的样本。很多人第一次看时被第一行误导,其实应该看后面的行。我习惯执行 vmstat 1 10,取10个点,能覆盖一个大约9秒的窗口。如果要排查持续性问题,可以 vmstat 1 30,再配合watch或重定向到文件。

输出分六大列:procs、memory、swap、io、system、cpu。每一列里有细分字段。不要一股脑全看,按当前怀疑的方向挑重点。

3.2 procs里的r和b,是阻塞的最直接信号

procs列下的r表示当前等待运行队列中的进程数,b表示处于不可中断睡眠状态的进程数。很多人只关心CPU使用率,忽略了r。其实r才是判断CPU是否饱和的核心指标:如果r长期大于CPU核心数,说明很多线程在排队等待CPU,即使us不是100%,系统也已经算过载了。b如果持续不为0,一般是IO存在问题,某进程在等磁盘或网络等外部资源。

我记得一次排查某应用性能下降,us和sy都不高,CPU有大量空闲,但是r排队很长,应用响应依然慢。后来发现是线程池配置过小,任务都堆积在用户态队列里,和CPU其实没直接关系。这也说明vmstat的r值要看,但还要结合进程内线程状态综合判断。

3.3 memory和swap:si/so 不是随便看看

memory列有swpd、free、buff、cache。swpd表示已经使用的交换分区大小,free是空闲物理内存,buff是块设备缓冲,cache是页面缓存。很多人以为cache太大就是内存泄漏,其实恰恰相反,cache是Linux用来加速文件读写的,内存越空闲,Linux越倾向于把缓存做大。真正需要担心的字段是si和so,分别是每秒从swap换入、换出的量。如果so长期大于0,说明系统内存真的吃紧,正在把页面换出到磁盘;如果si也大,说明进程又要从swap读回来,频繁换页会让整个系统变慢,CPU可能有大量sy或wa。

有时候free显示swpd为0,但si/so有流量,因为内核可能在回收页面。大多数时候只要so不为0,就要警惕内存压力,下一步用free -h看看available是不是已经逼近安全线。

3.4 io、system和cpu配合读

io列有bi和bo,分别是每秒从块设备读入和写入的块数(单位是块)。这个数字大说明磁盘读写频繁,但没法区分是缓存命中还是真实IO,所以不能单独拿来判断磁盘性能瓶颈,更适合配合iostat看设备队列和等待时间。system列包括每秒中断数in和每秒上下文切换数cs,上下文切换高说明系统里进程和线程频繁切换,常和线程数量过多、锁竞争或者syscall过多有关。cpu列在前面top里已经讲了一部分,vmstat的好处是每个采样点单独输出,能看出来us/wa随着时间的变化趋势,是平滑升高还是突然尖刺。

3.5 怎么用vmstat快速定位瓶颈

实战中我会这样用:先执行vmstat 1 5,看r是否大于CPU核数,b是否持续非0;如果b高,再看wa是否高;如果wa高,跳过去看iostat;如果si/so有值,去看free -h;如果cs特别高,先去分析进程的线程行为。这条判断路径几乎可以应对80%的“服务器突然变慢”问题。vmstat不能告诉你具体是哪个进程造成的,但它能帮你锁定方向,缩小范围。

4. free:别再被“buff/cache”绕晕了

4.1 默认的free输出,很多人看错

直接执行free -h,输出里第一行是内存总数total、已用used、空闲free、共享shared、buff/cache和available。很多人在意used是不是很高,看到free很少就觉得内存快满了。其实used这一项包含了page cache和buffer,这些缓存是可回收的,不可能按used直接判断内存压力。内核真正关心的,是系统还有多少内存可以立即分配给应用程序,这个数字就是available。

所以第一眼看free时,我只看两个数:total和available。available是估算出的、在不触发swap的情况下还能分配给进程的内存量。如果available长期低于总内存的10%甚至5%,内存才真正紧张。free那列数值低,但available还很高,完全不用慌。

4.2 buff/cache回收机制和手动回收

Linux通过page cache缓存文件数据,读文件时会命中缓存,提升性能。当你看到cache占了大量内存,这是正常设计。需要缓存时,内核会清理cache来满足新分配需求。大多数情况下不需要手动执行echo 3 > /proc/sys/vm/drop_caches去清缓存,尤其在生产环境,强制清缓存会让文件读写性能暂时变差,还可能引发一些意外问题。我见过有人为了“释放内存”定时清缓存,结果数据库查询比平时慢了一倍。除非你在做性能基准测试,需要统一缓存状态,否则别去动它。

如果实在想确认内存使用情况,可以看/proc/meminfo里的MemAvailable、MemFree、Buffers、Cached、SwapTotal、SwapFree等更细粒度字段。有些命令显示的used减去buff/cache才是真正进程占用,但内核角度大家更认可available。

4.3 判断内存压力的几个信号

内存不足时,swap使用缓缓上升是第一个信号。free -h观察swap的used列如果持续增长,说明有些内存页被换出。第二个信号是available越来越低,同时si/so有值。第三个信号是OOM,但OOM是最后关头,生产环境最好别等到它出现。如果同时有缓慢的内存增长趋势,可能是应用在泄漏,可以持续记录free的输出,隔一段时间对比,或配合进程的RSS变化。RSS查看可以用ps aux --sort=-rss取前几,或者top按M排序后看RES列。RES是进程驻留内存,浪费较大时可以怀疑有泄漏。

但注意RES包括共享库和内存映射文件,并不等于私有内存。真要精确到进程,可以用smem命令(如果安装了)看PSS/USS。普通排查,以available和swap趋势为主就够了。

4.4 一个典型的误判场景

有个监控脚本每天检查free的used列,一旦超过90%就报警。结果这台机器天天报警,但实际上应用响应很正常。运维小哥被烦得不行,最后发现是Nginx加静态文件缓存,把大量磁盘文件读进page cache,used确实很高,但available一直很充裕,swap完全没动。把监控指标改成available之后,报警消失了。这就是free命令最常见的坑,希望你别再踩一次。

5. df:磁盘空间与inode,你只看到了一半

5.1 常规检查:空间使用率和挂载点

df -h输出每个文件系统的容量、已用、可用、使用百分比、挂载点。排查空间问题时,先找到使用率接近100%的挂载点。但在动手删除文件前,一定要确认这个目录下哪些文件占空间最大。这时候组合拳是df定位哪个挂载点满,du进入对应目录逐步定位大文件。最快的是du -sh /path/* | sort -rh 取前十,或者用du -ahx / 在一堆输出里找大的。注意du扫描整个根目录可能耗时很长,生产环境慎用,最好先从已知的常见大目录开始,比如/var/log、/home、/tmp、/opt。

5.2 空间满了但不知道谁占的:从文件系统层面排查

有个经典故障:df显示根分区100%,但用du -sh / 把整个根目录加起来,发现加起来的使用量远小于df的used值。这种情况大概率是文件被删除了,但还有进程保持文件句柄没有释放。删除文件只是删除了目录项,如果文件仍被某个进程打开,磁盘空间不会立即释放,直到进程关闭该文件或进程退出。查看方法是用lsof | grep deleted,或者lsof +L1直接列出link count为0但仍被打开的文件。找到进程后,要么重启进程,要么让应用自己关闭句柄。不处理的话,空间会一直被占用,日志可能一直在增长,把新写入彻底堵死。

5.3 inode用尽:df -h看不出问题,文件却创建不了

除了block空间,文件系统还有inode表,每个文件或目录至少一个inode。df默认显示的是数据块的使用率,即使数据块还有很多,inode耗尽也会导致“No space left on device”错误,但df -h看上去正常。检查方法就是df -i,看IUse%是否接近100%。inode耗尽常见于大量小文件场景,比如邮件队列、临时缓存目录、或者频繁创建小日志文件。遇到inode满,只能清理旧文件,或者把该目录挂载的文件系统重建为inode更多的文件系统(比如xfs的mkfs参数),但那是后话。应急时先find /path -xdev -type f找出数量巨大的目录,然后清理不需要的文件。

5.4 df -T和挂载类型

df -T可以额外显示文件系统类型,比如ext4、xfs、nfs、tmpfs。这个参数在排查网络文件系统时特别有用,如果你发现df执行非常卡顿,很有可能是NFS挂载的远程目录失联或超时,df会卡在那里等IO。处理方式是先检查NFS挂载状态,或者把失联的挂载点卸载。系统启动时自动挂载的配置在/etc/fstab里,如果NFS挂载点出问题,系统启动也可能卡住。df -T能帮你快速看哪些是网络文件系统,以便调整排查策略。还有tmpfs类型的挂载点(如/dev/shm),占的是内存,空间大小和内存有关,不能按磁盘思路清理。

6. iostat:磁盘IO的延迟、队列和吞吐量分析

6.1 先看扩展统计,别用默认输出

Linux自带的iostat默认输出相当有限,只有tps和KB_read/s等简单信息,很难判断瓶颈。实际排查都用iostat -x -d 1,-x表示显示扩展统计,-d表示只显示设备,1是采样间隔。如果要持续看,iostat -x -d 1 5就是采样5次。输出里会看到Device、r/s、w/s、rkB/s、wkB/s、avgqu-sz、await、r_await、w_await、svctm、%util等字段。第一次看到这些英文缩写可能发懵,但它们其实描述了磁盘每个细分维度的状态。

6.2 关键字段的含义和判断经验

r/s和w/s是每秒读/写请求次数,rkB/s和wkB/s是每秒读写数据量。直接对比可以判断这台磁盘的吞吐是请求多还是数据量大。avgqu-sz是平均请求队列长度,队列太长说明请求在排队,磁盘处理不过来。await是每次IO请求的平均处理时间(毫秒),包括在队列里等待的时间和实际处理时间。r_await和w_await则分别拆开读和写。%util表示设备在采样周期内有百分之多少时间在处理IO,很多人以为%util到100%磁盘就满了,其实对于多盘(如硬件RAID)或固态硬盘,100%也不一定是上限,需要综合看。

我的实践判断:普通机械盘,如果await超过20ms甚至30ms,说明已经明显变慢;SSD通常应在个位数毫秒,高负载时会到十几毫秒。%util接近100%且avgqu-sz不断增加,说明磁盘确实处于高负载;但如果%util高但await不高、队列也短,可能是在处理大量小IO,并发能力还可以。不能只看单个指标,要把队列长度和请求耗时放一起看。

6.3 瓶颈方向:是磁盘慢,还是上层请求太猛

如果r/s和w/s非常高,先看是什么进程在发起请求。用iotop(非默认安装)可以按进程显示IO,非常直观。没有iotop时,也可以用pidstat -d,或者从vmstat的bi/bo里看到整体IO量,再结合ps和进程行为猜测。磁盘慢时iostat的%util会高,但请求量不一定很大,有可能是单次IO随机读写、寻道开销大,await就会高。而如果请求量大但%util不高,则可能是上层应用并发不足和文件系统缓存命中率高,实际落盘很少。

6.4 实际举例:一条iostat输出怎么读

比如iostat -x -d 1输出:sda r/s=20 w/s=180,rkB/s=500,wkB/s=18000,avgqu-sz=8.5,await=35.6,r_await=12.3,w_await=39.1,%util=98。这个场景基本是写多读少,写延迟将近40ms,队列长度8.5说明每次都排队,磁盘已经在满负荷工作。这时如果是数据库,就要考虑优化写入模式、批量提交或扩充磁盘能力。如果是日志写入,可以考虑异步落盘或换更快的设备。再配合top查看谁在使用CPU,可能发现某个进程同步写文件导致整个系统慢,这时优化方向就明确了。

7. 实战:一次模拟数据库卡顿的完整排查链路

为了把这五个命令串起来,我模拟一次故障过程。某业务系统突然响应变慢,运维进去后用top、vmstat、free、df、iostat一步步定位,整个过程不复杂,但顺序很重要。

7.1 进入系统先看top

top -bn1快速看一眼load average,发现load已经从正常的2左右涨到9,14个核心的系统明显过载。进程列表里,数据库进程CPU占150%(多线程下超过100%正常),看起来还行;但排在最前面的CPU使用率并不高,这就奇怪了。再看CPU状态,us约25,sy约5,wa高达62,这是典型IO等待。内存看起来也用了不少,free命令显示available只有8G,总共64G,还有余量但不算宽裕。

7.2 vmstat确认阻塞点是IO

执行vmstat 1 5,第一行忽略,看后面四行,r大概在3到5之间,b却几乎一直是2或者3。b持续非0,说明有进程卡在不可中断睡眠状态,而这类状态多数是等磁盘。si/so为0,排除swap压力。cs上下文切换每秒接近4万,有点高,但结合wa高,更像是IO阻塞导致的频繁调度。现在基本可以断定瓶颈在磁盘IO,不是CPU也不是内存。

7.3 iostat定位到具体设备

执行iostat -x -d 1 5,发现数据库所在的sdb设备%util稳定在99%,avgqu-sz一度到15,await平均值到45ms。这说明磁盘确实被压满了。再看r/s和w/s,读请求不多但写请求很高,wkB/s并不算特别大,说明是大量小写请求把队列堆满了。数据库每秒写很多小事务,随机写导致磁盘寻道压力大,机械盘特性直接被放大。

7.4 df和inode核查

顺手执行df -h和df -i,空间很充足,inode使用率也只有30%,排除磁盘满和inode满。到这里,问题根因明确:数据库日志或频繁小事务写入导致磁盘IO饱和。进一步检查发现应用层开启了同步提交或同步刷盘配置,每次事务都强制写盘。调整批量提交策略,缓冲一段时间再写,实测tps恢复,load回落到2.5,wa降到10%以下。

7.5 这个排查链路的通用价值

整个过程中top给总体方向,vmstat确认瓶颈类型,iostat定位设备,free和df排除内存与空间干扰。这五条命令顺序执行,十几分钟就能有一个明确结论,不需要装额外工具。在生产环境中,这种排查思路可以复制到很多相似的性能问题里,并不是某个特定数据库的专属套路。

8. 我把这些命令用熟的几个经验和坑

8.1 用watch命令让输出自动刷新

排查现场想持续观察top、vmstat或iostat,不要开几十个终端窗口。用watch -n 1 'vmstat 1 2'既能看到两次采样,又保持屏幕稳定。也可以watch -d 'free -h',-d会高亮变化的部分,长时间观察内存增长特别有用。iostat用watch刷新时,建议用iostat -x -d 1 2,别用iostat -x -d 1,否则默认只输出一次就结束了刷新窗口。

8.2 采样时间别太短,尤其别拿单点下结论

很多人执行vmstat或iostat只取一次,第一次输出的还是系统平均或者瞬时值,很容易误判。比如某应用每5秒做一次大IO,单次看wa可能只有10%,连续看10个点就能发现规律。我几乎不会用单次结果做判断,至少要连续采样3次以上。采样期间如果系统负载刚起来,也得留出时间让负载充分体现,否则看到的都是过渡状态。

8.3 这些命令在精简系统里可能没有

有些容器或最小化系统里iostat不在,因为sysstat包没装。这时候可以先看/proc/diskstats、/proc/stat、/proc/meminfo,它们提供底层数据。vmstat某些老版本没有available字段,可以看free命令的available或者读取/proc/meminfo的MemAvailable。生产环境想用工具,最好提前在镜像或安装脚本里备好sysstat、procps等基础包,别等故障了再发现装不上或没权限。

8.4 远程操作时小心终端卡住

在慢终端或网络抖动时执行top全屏交互式,如果中途卡住可能回不到命令行。习惯做法:需要采集输出时用top -bn1代替top;需要观察趋势时结合watch或重定向输出到文件。重定向之后还能事后分析,比如top -bn1 > top_$(date +%s).log,配合脚本生成汇总。

最后再分享一个小习惯:我会把一次完整的排查记录全部存下来,包括top、vmstat、free、df、iostat的输出和最终处理动作。下次遇到类似问题,翻记录比拍脑袋快得多。这些命令真正有价值的地方不是单条输出,而是组合起来之后能告诉你系统正在经历什么。希望你也能把这套思路用在日常运维里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询