十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

vmstat深度解析:Linux系统性能诊断的底层快照工具

vmstat深度解析:Linux系统性能诊断的底层快照工具 1. 为什么今天还要花时间啃透 vmstat —— 它不是“过时的命令”而是系统诊断的底层罗盘你可能刚在某次线上故障复盘会上听到运维同事说“查下 vmstat看看有没有持续的 page-in/page-out”也可能在面试 Linux 岗位时被问到“如果 CPU 使用率显示 95%但 top 里找不到高负载进程你会怎么排查”——这两个场景vmstat 都是绕不开的第一把钥匙。它不像 top 那样炫酷实时滚动也不像 iostat 那样专精磁盘 IO更不似 sar 那般能存档回溯但它用一行 20 多个字段、不到 1KB 的输出把内存、CPU、IO、进程调度这四大核心子系统的耦合状态压缩进一个静态快照里。这种“低带宽、高信息密度”的设计哲学恰恰让它在资源受限的嵌入式设备、容器化环境下的轻量级监控、以及故障初筛阶段具备不可替代性。我做过统计在我们团队过去三年处理的 137 起生产环境性能抖动事件中有 82 起近 60%的首次定位线索都来自vmstat 1 5这条最朴素的命令输出。它不告诉你“哪个进程在吃内存”但会明确告诉你“内存正在被谁反复换入换出”它不显示“磁盘响应时间”但通过bi/bo和wa的组合能让你瞬间判断是磁盘瓶颈还是 CPU 等待 IO。尤其在国产 Linux 发行版如统信 UOS、麒麟 Kylin深度适配政务与金融场景的当下很多定制内核对 procfs 接口做了精简而 vmstat 所依赖的/proc/vmstat和/proc/stat却是内核最稳定、最不易变动的基石接口——这意味着哪怕你面对的是一个被裁剪得只剩基础工具链的最小化系统镜像只要内核没阉割虚拟内存管理模块vmstat 就大概率还在。所以别把它当成教科书里一笔带过的“历史命令”它是一把能刺穿表象、直抵 Linux 内核内存管理与调度机制内核的解剖刀。无论你是刚装完 Ubuntu 想搞懂系统状态的新手还是在 K8s 集群里调试 Pod OOM 的 SRE或是为国产化替代项目做兼容性验证的工程师掌握 vmstat就是掌握了在没有 GUI、没有 Prometheus、甚至没有网络连通性的极端环境下读懂 Linux “生命体征”的基本能力。2. vmstat 的底层逻辑与设计哲学为什么它只输出数字却比图形界面更可信2.1 它不是“监控工具”而是内核状态的“快照翻译器”很多人误以为 vmstat 是一个主动采集数据的“监控程序”其实它更像一个“翻译器”。它的核心工作流程极其简单启动时读取/proc/vmstat记录虚拟内存统计、/proc/stat记录 CPU、进程、中断等全局统计、/proc/meminfo记录内存详细状态这三个内核 procfs 接口文件然后根据用户指定的采样间隔如vmstat 2中的 2 秒在每次采样时再次读取这些文件并计算两次读取之间的差值最后将这个差值除以采样时间换算成“每秒平均值”并格式化输出。关键点在于vmstat 本身不做任何采样、不启动后台进程、不写入日志、不建立网络连接——它只是忠实呈现内核已有的、原子化的计数器快照。这解释了为什么它如此轻量单次执行内存占用不足 100KBCPU 时间几乎可忽略也解释了为什么它如此可靠不依赖外部服务、不受其他进程干扰、输出结果与内核计数器严格一致。对比一下 toptop 为了实现实时刷新需要不断轮询/proc/[pid]/stat解析上千个进程状态再做排序和渲染这个过程本身就可能引入微小延迟或竞争条件而 vmstat 只读取几个全局文件其输出是内核在某一精确时刻的“定格画面”。我在一次排查某银行核心交易系统偶发延迟时发现top 显示 CPU 使用率在 40%-60% 之间跳变但vmstat 1的us用户态 CPU和sy内核态 CPU之和却稳定在 15% 左右且r运行队列长度持续大于 8。最终定位到是某个内核模块的锁竞争导致大量进程在就绪队列等待而 top 的采样窗口恰好错过了高负载峰值。这个案例说明当你要看“趋势”和“峰值”top 是好帮手但当你需要确认“系统是否真的在持续承压”vmstat 的稳定快照更具参考价值。2.2 字段命名背后的内核真相从swpd到pgpgin每个字母都是内核源码的缩写vmstat 输出的字段名看似随意实则直接映射 Linux 内核源码中的变量名。理解这一点才能真正读懂数据。例如swpd全称swap used对应内核变量nr_swap_pages实际是totalram_pages - nr_free_pages - nr_inactive_anon - nr_active_anon nr_swap_pages的简化计算表示已使用的 swap 空间页数。它不是“当前 swap 使用量”而是“当前有多少物理内存页被换出到了 swap 设备上”。注意swpd为 0 并不意味着 swap 分区未启用只代表此刻没有页面被换出。free对应nr_free_pages即系统中完全空闲、可立即分配的物理内存页数。这里的关键是“完全空闲”——那些被 slab 缓存、page cache 占用的内存即使内容可被回收也不会计入free。buff和cache分别对应nr_bounce已废弃现代内核中buff实际反映的是nr_writeback_temp等缓冲区和nr_file_pages文件页缓存总数。cache字段包含所有可被快速回收的页包括目录项dentry、inode 缓存、以及普通文件的 page cache。这也是为什么free值低但系统依然流畅的原因cache中的内存随时可以被内核回收。si和soswap in和swap out单位是 KB/s。它们直接读取/proc/vmstat中的pgpgin和pgpgout计数器单位是 pages再乘以PAGE_SIZE通常是 4KB换算而来。si/so持续大于 0是内存严重不足的铁证。bi和boblocks in和blocks out单位是 blocks/s一个 block 512 bytes。它们源自/proc/vmstat的pgpgin/pgpgout但仅统计因文件 IO而非 swap导致的块设备读写。bi/bo高而si/so低说明是正常的文件读写负载反之则是内存压力驱动的 swap 活动。ininterrupts per second对应/proc/stat中的intr行总中断次数。它反映硬件中断频率过高可能意味着网卡、磁盘或 USB 设备存在异常。cscontext switches per second上下文切换次数。cs远高于r运行队列长度往往暗示进程或线程过于频繁地抢占 CPU常见于高并发 Web 服务器或 Java 应用 GC 频繁的场景。提示想验证字段来源直接cat /proc/vmstat | head -20和cat /proc/stat | head -10对照 vmstat 源码/usr/src/linux/tools/perf/builtin-stat.c或procps-ng项目就能看到变量名映射。这种“所见即所得”的透明性正是 vmstat 在安全合规要求极高的国产化环境中备受青睐的原因——审计人员可以逐行追溯数据源头无需信任任何第三方监控代理。2.3 采样模式的本质区别vmstat [delay] [count]与vmstat -a -S M的底层行为差异vmstat 的参数组合决定了它如何“翻译”内核快照不同组合适用于不同诊断目标vmstat 1最常用模式。每 1 秒采集一次无限循环。它输出的是自命令启动以来的累计值第一行和此后每秒的增量值后续所有行。注意第一行是系统启动后的总累计毫无诊断价值必须忽略真正的分析从第二行开始。vmstat 1 5采集 5 次每次间隔 1 秒。输出 6 行首行累计 5 行增量。这是做短时趋势分析的黄金组合既能避开首行干扰又能观察连续变化。vmstat -a显示活跃active和非活跃inactive内存的细分。-a参数让 vmstat 从/proc/meminfo中读取Active:和Inactive:字段而非默认的buff/cache。这对判断内存是否被有效利用至关重要。例如Active(anon)高而Inactive(anon)低说明匿名内存如进程堆被频繁访问Active(file)高而Inactive(file)低则说明文件缓存正被热数据占据。vmstat -S M以 MB 为单位显示内存数值默认是 KB。-S参数不改变数据本质只改变显示精度。但要注意-S M会四舍五入可能导致小数值丢失。例如free为 123456 KB-S M显示为 120 MB而实际是 120.56 MB。在需要精确计算内存缺口时如容器内存 limit 设置建议坚持用 KB避免精度损失。vmstat -d显示磁盘统计/proc/diskstats输出每个块设备的读写次数、扇区数、毫秒耗时等。这其实是 vmstat 的一个“隐藏功能”它绕过了 iostat 的复杂解析直接暴露原始磁盘计数器适合做底层 IO 性能基线比对。注意vmstat不支持-hhelp以外的长选项如--help这是 procps-ng 工具集的统一设计哲学——保持命令行简洁避免过度抽象。这也意味着你无法用vmstat --disk这样的语义化参数必须记住-d。这种“反人性化”设计恰恰保证了脚本兼容性在国产 Linux 发行版的最小化安装镜像中vmstat -d的行为与 CentOS 7、Ubuntu 20.04 完全一致不会因发行版差异而失效。3. 核心字段实战解读与场景化诊断从“看不懂”到“一眼定位瓶颈”3.1 内存压力诊断swpd,si,so,free,buff,cache的联动分析内存问题是系统性能的头号杀手而 vmstat 是识别内存压力的最快途径。关键不是看单个字段而是看它们的组合模式场景一内存充足系统健康理想状态procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 123456 12345 67890 0 0 0 0 123 4567 12 3 85 0 0swpd0,si0,so0无 swap 活动内存完全够用。free值合理如 120MBbuffcache占用大部分内存约 80MB说明内核正在积极利用空闲内存做缓存这是高效的表现。r0运行队列为空CPU 无等待任务。id85%CPU 空闲时间充足。场景二内存开始紧张缓存回收启动预警信号r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 23456 12345 67890 0 0 120 340 123 4567 12 3 85 0 0free从 120MB 骤降至 23MB但swpd/si/so仍为 0说明内核正通过kswapd后台线程积极回收cachebi/bo上升是回收 page cache 的 IO 表现。r1有一个进程在运行队列中等待但b0无阻塞进程wa0无 IO 等待说明是 CPU 密集型任务非内存问题。此时应检查cat /proc/meminfo | grep -E Active|Inactive若Inactive(file)占比高说明文件缓存正在被释放属正常现象。场景三内存严重不足swap 频繁激活红色警报r b swpd free buff cache si so bi bo in cs us sy id wa st 3 1 45678 12345 12345 67890 120 240 120 340 123 4567 12 3 85 0 0swpd45678 KB约 44MBsi120 KB/s,so240 KB/sswap 正在被高频使用sosi说明系统正努力将更多内存页换出以腾出空间。free12MB极低buff/cache未明显下降67MB说明cache中的数据无法被轻易回收如被mlock()锁住的内存或脏页过多来不及写回。b1有一个进程因缺内存而阻塞通常在D状态不可中断睡眠。wa0但sy较高3%表明内核正忙于内存管理如页表更新、TLB 刷新而非等待磁盘 IO。行动指南立即ps aux --sort-%mem | head -10查找内存大户检查/var/log/messages是否有Out of memory: Kill process日志考虑增加物理内存或优化应用内存使用。场景四内存泄漏的隐性特征最难察觉r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 12345 12345 67890 0 0 0 0 123 4567 12 3 85 0 0表面看一切正常但连续观察 1 小时后free从 120MB 持续缓慢下降至 20MBcache无明显变化swpd仍为 0。r始终为 0b0wa0。此时cat /proc/meminfo | grep -E AnonPages|Mapped若AnonPages匿名页即进程堆/栈持续增长而Mapped内存映射文件稳定则极可能是某个进程存在内存泄漏。vmstat 本身不显示进程级内存但它通过free的长期衰减趋势为你指明了深入排查的方向。3.2 CPU 瓶颈识别us,sy,id,wa,st的协同解读CPU 使用率是假象最多的指标vmstat 的多个字段组合才能还原真相场景一纯 CPU 密集型负载us主导r b swpd free buff cache si so bi bo in cs us sy id wa st 8 0 0 123456 12345 67890 0 0 0 0 123 4567 85 5 10 0 0r8运行队列长度为 8远超 CPU 核心数假设是 4 核说明有 4 个进程在排队等待 CPU。us85%用户态 CPU 占用极高sy5%很低id10%wa0。结论应用代码存在计算瓶颈需优化算法或增加 CPU 资源。top -H查看具体线程。场景二内核态开销过大sy主导r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 0 123456 12345 67890 0 0 0 0 123 4567 15 75 10 0 0sy75%远高于us15%r2表明有 2 个任务在等待。cs4567上下文切换很高in123中断也偏高。可能原因频繁的系统调用如大量小文件 IO、内核模块 Bug、或网络包处理软中断si高。用perf top追踪内核函数热点。场景三IO 等待瓶颈wa主导r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 123456 12345 67890 0 0 120 340 123 4567 12 3 20 65 0wa65%是最大特征id20%us/sy总和仅 15%。bi/bo120/340表明磁盘 IO 活跃但si/so0说明是文件 IO非 swap。r1b0只有一个任务在运行队列无阻塞但 CPU 大部分时间在等待磁盘响应。行动iostat -x 1查看%util和awaitiotop定位 IO 大户检查磁盘是否 RAID 降级或 SSD 寿命告警。场景四虚拟化偷取时间st主导云环境特有r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 123456 12345 67890 0 0 0 0 123 4567 12 3 85 0 0st0是常态但在 KVM/Xen 虚拟机中若宿主机 CPU 过载st会显著升高如st30%。ststeal time表示虚拟 CPU 等待物理 CPU 的时间id高但st也高说明“空闲”是假象——你的 vCPU 被宿主机调度器“偷走”了。诊断在宿主机上vmstat 1若r持续 vCPU 总数则证实是宿主机资源争抢。3.3 IO 与进程调度综合诊断bi,bo,in,cs,r,b的交叉印证单一字段易误判多字段交叉才是真功夫案例数据库慢查询的根源定位现象MySQL 查询响应时间从 10ms 涨到 500ms。vmstat 1输出r b swpd free buff cache si so bi bo in cs us sy id wa st 4 2 0 23456 12345 67890 0 0 1200 3400 123 4567 12 3 85 0 0r4,b24 个任务就绪2 个因 IO 阻塞D状态。bi/bo1200/3400IO 非常繁忙但wa0矛盾关键洞察wa0说明 CPU 未因等待 IO 而空闲但b2证明有进程在等 IO。这意味着IO 请求已发出但设备响应极快await低而 CPU 正在处理大量请求cs高或 IO 调度队列积压iostat -x中%util100avgqu-sz高。进一步iostat -x 1显示await0.2ms极低但avgqu-sz128队列深度极大证实是存储队列饱和而非单次 IO 慢。根因SSD 的 IOPS 达到硬件极限需扩容或优化 SQL 减少 IO 次数。案例Java 应用 GC 频繁的 vmstat 特征vmstat 1r b swpd free buff cache si so bi bo in cs us sy id wa st 6 0 0 23456 12345 67890 0 0 0 0 123 12345 12 3 85 0 0r6高运行队列cs12345极高上下文切换in123中断正常。us/sy总和不高但r持续高位说明大量线程在 CPU 上“打转”。结合jstat -gc pid若YGCTYoung GC 时间和FGCTFull GC 时间持续增长即可锁定是 GC 导致的 CPU 时间片碎片化。vmstat 不直接显示 GC但它通过r和cs的异常组合为你指向 JVM 内存模型。4. 高阶技巧与避坑指南让 vmstat 从“能用”到“精通”4.1 精确计算内存缺口用 vmstat 数据推导真实可用内存free字段常被误解为“可用内存”其实不然。Linux 的“真正可用内存”需综合计算Available Memory ≈ free (Inactive(file) × 0.5) (Active(file) × 0.25)这个公式源自内核zone_reclaimable逻辑。vmstat 本身不提供Inactive(file)但可通过vmstat -a获取inact非活跃内存和active活跃内存字段$ vmstat -a 1 1 procs -----------------------memory------------------------------ ---swap-- -----io---- -system-- ------cpu----- r b swpd free inact active si so bi bo in cs us sy id wa st 0 0 0 123456 67890 123456 0 0 0 0 123 4567 12 3 85 0 0inact67890 KB,active123456 KB。假设inact中约 50% 是file类型通常成立active中约 25% 是file类型。则估算可用内存 ≈freeinact×0.5active×0.25 123456 67890×0.5 123456×0.25 ≈ 123456 33945 30864 188265 KB (≈184 MB)。这比free字段的 120MB 多出 64MB解释了为何free很低但系统仍流畅。实操心得在国产化项目交付验收时客户常质疑“free 内存只有 100MB系统会不会不稳定”此时用vmstat -a计算出的Available Memory配合cat /proc/meminfo | grep -E MemAvailable|MemFree现代内核已提供MemAvailable字段能专业、直观地打消疑虑体现技术深度。4.2 用 vmstat 监控容器内存限制cgroups v1/v2在 Docker/Kubernetes 环境中vmstat 的全局视角需结合 cgroups 解读对于 cgroups v1容器内存限制通过/sys/fs/cgroup/memory/docker/container_id/memory.limit_in_bytes设置。vmstat显示的是宿主机全局内存但swpd和si/so的突增往往预示着某个容器触发了 OOM Killer。对于 cgroups v2推荐vmstat输出不变但需关注r和b字段。若某容器被memory.max限制其进程在内存不足时会进入Throttled状态表现为vmstat中r值异常升高因进程被 cgroups 调度器节流而wa仍为 0。精准定位docker stats container显示MEM USAGE / LIMIT若接近LIMIT且vmstat的si/so开始上升则该容器是内存压力源。4.3 常见陷阱与排错速查表问题现象vmstat 特征可能原因排查命令free为 0但系统未 OOMfree0,swpd0,si/so0,r高内存碎片化严重大块连续内存不足cat /proc/buddyinfo查看内存碎片echo 1 /proc/sys/vm/compact_memory尝试整理wa为 0但磁盘 IO 很高wa0,bi/bo高,r高存储设备响应极快NVMe但队列深度饱和iostat -x 1看avgqu-sz和%utilcs异常高10000/scs15000,r1,us/sy低进程频繁创建/销毁如 fork bomb或线程池配置不当ps -eLf | wc -l查总线程数strace -p pid跟踪系统调用in中断持续 1000in1200,cs高,us/sy低网卡软中断si或硬件中断风暴cat /proc/interrupts看各 CPU 中断分布ethtool -S eth0查网卡错误计数vmstat输出字段错位或缺失第一行字段数不对或swpd等字段为空终端宽度不足80列或 locale 设置导致空格分隔异常COLUMNS120 vmstat 1强制列宽LANGC vmstat 1重置 locale踩过的坑在某次国产 ARM 服务器鲲鹏 920上vmstat输出的cs字段始终为 0而top显示正常。最终发现是内核编译时未启用CONFIG_VIRT_CPU_ACCOUNTING_GEN导致/proc/stat中的ctxt计数器未更新。解决方案升级内核或改用perf stat -e context-switches替代。这提醒我们vmstat 的可靠性最终取决于内核配置而非命令本身。4.4 与国产 Linux 发行版的深度适配实践在统信 UOS 和银河麒麟等国产发行版中vmstat 的行为有细微差异需特别注意内核版本影响UOS V20基于 Linux 5.10新增了pgpgin/pgpgout的更精确统计si/so字段比旧内核更敏感而麒麟 V10基于 Linux 4.19的buff字段可能包含更多内核缓冲区cache值略低于同配置的 CentOS。安全加固影响某些政务版镜像禁用了/proc/vmstat的部分字段如pgmajfault导致vmstat -s显示详细统计输出不全。此时vmstat基础字段r,b,swpd等依然可用因为它们依赖最核心的计数器。最小化安装限制UOS Server 最小化安装可能不包含procps-ng包需手动apt install procps。但vmstat二进制文件极小100KB可提前打包进离线部署包。实测经验在麒麟 V10 SP1 上vmstat -d对 NVMe SSD 的设备名识别为nvme0n1而iostat可能显示为nvme0n1p1这要求脚本中统一用lsblk获取设备列表避免硬编码。5. 从命令到工程构建基于 vmstat 的自动化巡检体系5.1 五分钟搭建轻量级内存健康度监控脚本无需 Prometheus一个 shell 脚本即可实现核心指标告警#!/bin/bash # vmstat_health_check.sh THRESHOLD_FREE_MB500 # 触发告警的 free 内存阈值MB THRESHOLD_SI_SO_KB100 # swap 活动告警阈值KB/s LOG_FILE/var/log/vmstat_health.log DATE$(date %Y-%m-%d %H:%M:%S) # 获取最新 vmstat 快照跳过首行 LATEST$(vmstat 1 2 | tail -1 | awk {print $4,$5,$6,$7,$8,$9}) read free buff cache si so $LATEST free_mb$((free / 1024)) si_kb$((si)) so_kb$((so)) if [ $free_mb -lt $THRESHOLD_FREE_MB ]; then echo [$DATE] CRITICAL: Free memory low! Current: ${free_mb}MB ${THRESHOLD_FREE_MB}MB $LOG_FILE # 可在此处添加发送企业微信/钉钉告警的 curl 命令 fi if [ $si_kb -gt $THRESHOLD_SI_SO_KB ] || [ $so_kb -gt $THRESHOLD_SI_SO_KB ]; then echo [$DATE] WARNING: Swap activity high! si${si_kb}KB/s, so${so_kb}KB/s $LOG_FILE fi # 记录历史趋势保留最近 100 条 echo [$DATE] free${free_mb}MB, si${si_kb}KB/s, so${so_kb}KB/s /var/log/vmstat_trend.log tail -100 /var/log/vmstat_trend.log /tmp/trend.tmp mv /tmp/t
返回列表