做Linux性能排查,iostat命令是我每次必用的性能监控工具之一。它不像vmstat那样只给个整体概况,也不像sar那样要事后翻历史曲线,iostat能在现场直接输出CPU和磁盘的实时I/O统计,几秒钟就能判断系统到底卡在CPU还是卡在磁盘。无论是看数据库服务器变慢、定位日志写盘异常、还是排查虚拟机宿主机的高负载问题,iostat都是第一梯队要上的命令。这篇就围绕iostat命令本身,把安装、参数、输出指标、常见坑和实战判断思路一次讲透,适合刚接触Linux运维的初学者,也适合那些已经会敲iostat但不知道输出结果意味着什么的人。
1. iostat是什么:先从整体认识这个性能监控工具
1.1 它来自sysstat工具包,和sar同门
iostat全称是I/O statistics,意思是输入输出统计,它并不是一个孤零零的命令,而是sysstat工具包里的成员。sysstat包里还有sar、mpstat、pidstat、cifsiostat这些常用工具,它们都共用一套内核数据读取机制,所以如果你装过sar,iostat大概率已经躺在系统里了。
排除掉少数定制化系统的特殊情况,iostat的数据来源是内核维护的/proc/stat和/proc/diskstats这两个虚拟文件。proc目录不是真正存在磁盘上的文件,它是由内核动态生成的窗口,iostat做的事就是定时去读这些计数器的数值,然后计算两次采样之间的差值,再除以间隔时间,换算成每秒的速率。这也是为什么iostat必须“隔一段时间采样两次以上”才能算出速率,单独跑一次不带参数的命令,它显示的是开机到现在的平均数据。
这个数据来源决定了iostat能看到非常底层的真实情况,它绕过文件系统缓存,直接反映块设备层的I/O行为,这是很多应用层工具做不到的。比如你通过df看到磁盘满了,通过top看到CPU跑满了,但磁盘到底有多少读写压力、请求平均等多久、设备忙不忙,这些只有通过iostat这类块设备层工具才能看到。
1.2 核心功能:一块看CPU,一块看磁盘
iostat的输出天然分成两大块,这是它设计上最直观的特点。第一块是CPU使用率统计,占据顶部区域,包含%user、%system、%iowait、%idle等字段,可以快速判断CPU是不是被用户程序占满,或者系统CPU花在等待I/O上。
第二块是设备使用率统计,也就是Device表。默认情况下它列出的是系统里的物理磁盘和分区,比如sda、sdb、nvme0n1这些,每一行都是一个独立的块设备。这块表里的列很多,包含每秒传输次数tps、每秒读写的数据量、平均I/O等待时间await、设备繁忙程度%util等,这也是iostat作为“性能监控工具”最核心的价值所在。
这两块数据的意义在于配合判断。CPU的%iowait指标抬高,只能告诉你“有程序在等I/O完成”,但具体是哪个磁盘拖后腿、等多久、请求积压多少,必须看下面设备表里的指标。很多新手只盯CPU,看到%iowait高就慌,却不知道源头在哪,iostat把这两块放在同一个输出里,就是为了让人能快速联动分析。
1.3 这东西适合谁来用,能解决什么问题
iostat适合的角色非常广。如果你是Linux运维工程师,服务器无端变慢、数据库查询变慢、应用超时报警,这些场景基本绕不开iostat。如果你是开发人员,程序执行效率低、批量任务跑得慢,也可以用它确认瓶颈是不是落在磁盘I/O上,而不是一上来就怀疑代码有问题。如果你是面试官视角,Linux命令里iostat出现的频率很高,能准确讲清楚%util、await、svctm含义的候选人,至少在性能排查方面是有点底子的。
它能解决的典型问题包括:确认系统瓶颈是CPU还是磁盘、定位是读瓶颈还是写瓶颈、判断某块磁盘是否已经饱和、验证调整参数后I/O性能有没有改善。它解决不了的问题也要心里有数:iostat看不到具体是哪个进程在读写,这要配合pidstat、iotop这类工具;它也看不到文件系统缓存层面命中多少,这要结合free和/proc/meminfo判断。先知道工具边界,用起来才不会走弯路。
2. 安装与基础用法:两条命令让你快速上手
2.1 不同发行版的安装方式
iostat通常不是最小化安装自带的命令,如果你敲iostat提示command not found,直接装sysstat包就行。不同发行版的包管理器不一样,安装命令差别不大,我列一下最常见的几类:
# Debian / Ubuntu 系列 apt install -y sysstat # CentOS / RHEL / Rocky / AlmaLinux 系列 yum install -y sysstat # 较新版本的 RHEL 系列用 dnf dnf install -y sysstat # openSUSE / SUSE zypper install -y sysstat # Arch / Manjaro pacman -S sysstat装完之后可以先跑一个iostat -V确认版本,不同版本的输出字段会有细微差别,比如较新的内核和sysstat版本里,%util的定义发生过调整,后面会专门讲。这里先提醒一句:如果apt或yum源里找不到,多半是软件源问题,不是命令本身的问题,更新软件源再装。
另外,sysstat包通常会附带安装一个定时任务,通过cron或systemd timer来定时收集性能数据到/var/log/sysstat目录,这是给sar用的历史数据源。iostat本身是随用随跑的实时工具,你不依赖历史库也一样能用,不冲突。
2.2 命令格式与常用参数清单
iostat的命令格式非常规整,基本可以概括为:
iostat [选项] [间隔时间] [次数]重点是间隔时间和次数这两个位置参数。间隔时间以秒为单位,次数表示采样输出多少次。比如iostat 2表示每2秒输出一次,一直循环;iostat 2 5表示每2秒输出一次,总共输出5次后就退出。实际排查问题的时候,我几乎总是用iostat -x 1 5这个组合,-x表示扩展统计,1秒间隔采样5次,既能覆盖一段时间的变化趋势,又不会让终端刷屏刷到失控。
常用参数我整理成一个表格,对照着看会更清楚:
| 参数 | 作用 | 使用要点 |
|---|---|---|
| -c | 仅显示CPU使用率 | 配合-d可单独确认CPU侧状态 |
| -d | 仅显示磁盘I/O统计 | 输出更聚焦,推荐日常使用 |
| -k | 以KB为单位显示数据量 | 默认单位是块,不直观 |
| -m | 以MB为单位显示数据量 | 大吞吐场景比-k更易读 |
| -x | 扩展统计,显示更多指标 | 排查瓶颈时必加 |
| -t | 在输出中显示时间戳 | 记录现场数据时很实用 |
| -z | 不显示活动为0的设备 | 服务器磁盘很多时避免刷屏 |
| -h | 让输出更可读,面向NFS等信息 | 常规磁盘用不太上 |
| -y | 跳过第一次无间隔的统计信息 | 配合循环采样时更准确 |
参数之间可以组合,比如iostat -dxk 1 5表示以KB为单位、只看磁盘、扩展统计,每秒一次共5次,这是我很常用的组合。注意不要在一个命令里同时加-k和-m,单位会打架,系统会取最后一个生效,反而容易误导。
2.3 最常用的几种调用方式
第一种就是机房里最经典的裸奔式调用:直接敲iostat。这个不带任何参数,输出的是开机累计平均值,虽然不够实时,但可以快速看一个整体概况,比如系统是不是从启动到现在磁盘负载一直很高。
第二种是我说的iostat -dxk 1 5,这是标准实时体检。1秒的间隔比较激进,能捕捉到瞬时尖峰;如果你想看平稳趋势,把间隔拉到5秒或10秒更合适,比如iostat -dxk 5 5,这样采样的是5秒均值,噪音会小很多。
第三种是单独盯CPU,iostat -c 1 3,这在怀疑CPU比磁盘更紧张的时候用。注意-iowait这个指标,它反映的是CPU花在等待I/O完成上的时间比例,这个值如果持续偏高,用iostat自己的话来说就是“CPU在等磁盘干活”,这时候你再切到-dx看设备详情,整个过程很顺。
提示:无论用哪种调用方式,采样次数都别设太少。至少3次以上再开始分析,因为第一次输出往往是当前瞬时状态的快照,波动很大。iostat -y参数可以跳过第一次无间隔的统计,做基准对比时很有用。
3. 输出结果逐项拆解:CPU和磁盘指标到底怎么看
3.1 第一块:CPU使用率的几个字段
用iostat -c 1 3跑出来的输出,头部会显示系统版本、日期和CPU核数,然后是一段avg-cpu表。这张表在非-x模式下显示的是百分比,各字段加起来接近100。常见字段有%user、%nice、%system、%iowait、%steal和%idle。
%user表示用户态程序占用的CPU百分比,%nice是低优先级用户态程序的占比,%system是内核态占比,%iowait表示CPU等待I/O完成的时间占比,%steal是虚拟机环境下被宿主机抢走的时间占比,%idle就是完全空闲的比例。这几个里面,%iowait是最值得留意的,它一高就说明有任务在等I/O,但要注意,%iowait高不高得多配合设备表看,如果%iowait很高但设备表的%util并不高,可能问题出在锁竞争、内存换页或者文件系统层。
读这段数据有个姿势上的讲究:别孤立看某一次采样,要看连续几次的变化趋势。比如%iowait从5%一路涨到40%,同时%user不变,那基本可以断定磁盘侧出问题了;如果%user本身就95%以上,那就是典型的CPU饱和,这时候再纠结磁盘没有意义。
3.2 第二块:Device表里的关键指标
Device表是iostat的精华,尤其加了-x参数后,列数会突然变多,很多人就是在这里开始看不懂的。默认模式下有tps、kB_read/s、kB_wrtn/s、kB_read、kB_wrtn这几列,-x模式下则多了r/s、w/s、rrqm/s、wrqm/s、r_await、w_await、aqu-sz、rareq-sz、wareq-sz、svctm、%util一堆字段。
逐一说太啰嗦,我挑几个最关键的讲。r/s和w/s是每秒读请求数和写请求数,这个“请求”不是应用层的read/write调用,而是真正下发到块设备层的I/O请求,所以它会比你在应用层看到的磁盘操作次数更贴近硬件。rkB/s和wkB/s是每秒读写的数据量,单位取决于你用-k还是-m。rrqm/s和wrqm/s是每秒合并的读、写请求数,I/O调度器会把相邻的小请求合并成大请求,这个值越高说明合并效率越好,对机械盘特别有利。
r_await和w_await是读、写请求的平均等待时间,单位毫秒,这个指标非常直观地反映“发出请求到完成”的延迟,是判断磁盘健康度的核心。aqu-sz是平均队列长度,代表有多少请求在排队。svctm是平均服务时间,也就是磁盘实际处理一个请求花的时间。最后是%util,设备繁忙百分比,算法是服务时间除以采样周期。这几个指标之间不是孤立的,它们的关系才是判断瓶颈的关键。
3.3 关键指标之间的关系与判断思路
很多人对iostat有个误解,以为%util到100%就意味着磁盘“满了”,这其实不太准确。%util反映的是设备繁忙的时间占比,但磁盘和CPU一样,处理请求是可以并行的,尤其现在SSD普遍是多队列设备,%util跑到100%不代表性能就到顶了。举个更生活化的例子:一条只允许一辆车通过的单车道,一旦有车在上面,这条路就100%占用,但它的吞吐量很有限;而一条八车道高速路,随时都有车在跑,占用率也高,但单位时间通过的车辆数远大于单车道。
所以判断磁盘是否成为瓶颈,我建议按这个顺序看:先看%util是不是长期接近100%,再看await是不是明显高于svctm,然后再看aqu-sz是不是持续增长。如果%util高、await远超svctm、队列长度也在涨,这三个同时满足,说明设备确实忙不过来,请求在排队,这就是真正的瓶颈。反过来,%util高但await和svctm差不多,队列长度也没有堆积,那可能只是设备在处理大量请求,但还应付得来。
这里有个经典的坑要提醒:老版本sysstat里svctm这个指标是统计出来的,新版本里它已经通过公式计算,在有的内核版本上计算方式发生过调整,所以svctm数值本身参考意义大于精确意义,不要用svctm去硬套“服务时间必须小于await”这种结论。更重要的是理解await和队列的增长逻辑。
注意:读await、aqu-sz、%util这三个指标时,一定要结合采样周期和I/O类型看。顺序读大文件时,即使磁盘很忙,await也未必高;但随机小IO密集时,即使%util看起来不高,await也可能已经很高。换句话讲,没有万能指标,组合着读才能下结论。
4. 实战记录:用iostat -x 1 5定位一次数据库卡顿
4.1 问题背景与初步判断
有一回帮朋友看一个MySQL数据库服务器,现象是业务侧反馈写入变慢,前端接口偶尔超时。服务器本身配置不低,CPU是16核,内存64G,系统盘和数据盘分开,数据用的是两块SSD做的软RAID1。朋友的初步怀疑是数据库连接数不够,加了连接数上限之后问题还在,于是让我上服务器看。
我先跑了一遍uptime和top,发现load average差不多在8左右,对16核机器来说不算爆表,但%wa这一项大概有20%多。这个%wa就是top里显示的I/O等待占比,比平时明显高。这个时候我基本锁定了方向:问题大概率出在I/O侧,而不是CPU算力不够。为了拿到更确切的证据,我把iostat叫上阵。
4.2 现场抓取数据并逐行解读
我当时执行的命令是iostat -dxk 1 5,输出非常清晰。第一段显示的是系统信息和CPU汇总,%iowait大概稳定在18%到23%之间。第二段设备表里最显眼的是sda这块盘,也就是数据盘所在的设备,几乎每一行都是满负荷状态。
截取其中一次采样的关键字段大概是这样的:
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util sda 12.00 156.00 120.00 50400.00 0.00 210.00 0.00 57.00 8.00 180.00 18.50 10.00 323.00 6.00 100.00我来拆解一下这张表的判断逻辑。w/s有156,这个数量不算高,但wkB/s有50400,约50MB/s的写入量,说明每次写请求的数据量不小,wareq-sz显示平均写请求大小约323KB,典型的日志顺序写特征。真正扎眼的是w_await,写等待平均180毫秒,而svctm只有6毫秒,差距非常悬殊,说明写入请求大部分时间不在设备上真正执行,而是在队列里干等。aqu-sz队列长度18.5,持续积压,%util长时间卡在100%。
这三个现象组合在一起,结论已经很明显了:这台机器的数据盘在处理写入时已经是排队状态,磁盘的写吞吐跟不上业务产生的写入量。SSD本身的svctm很低,但它扛不住请求堆积带来的等待激烈上升,表现在业务上就是写请求超时、接口响应变慢。
4.3 定位结论与后续处理建议
确认磁盘写瓶颈之后,我趁热打铁,又用pidstat -d 1 5看是哪个进程在大量写盘,结果抓到了mysqld,这跟业务反馈的数据库写入慢吻合。然后登录MySQL,用SHOW ENGINE INNODB STATUS和慢查询日志确认,发现有一个批量更新任务在频繁提交小事务,同时binlog和redo log都落在同一块数据盘上,刷盘压力集中爆发。
处理方案分了几步。第一步是临时缓解,把批量更新任务拆小,减少同时提交的事务数,拉平写入峰值,这个操作当天就让w_await从180毫秒降到了40毫秒左右。第二步是数据库参数调优,调整innodb_flush_log_at_trx_commit的取值,从每次提交都刷盘改为每秒刷一次,降低了fsync频率,这是牺牲一点崩溃恢复的实时性换写性能,要根据业务容忍度来定。第三步,如果有条件,把binlog和redo log分别放到不同物理设备上,避免所有写压力挤在同一块盘上。
这个案例最有价值的启发是:iostat自己不会告诉你哪个进程导致的I/O高,但它能极其准确地告诉你瓶颈在不在磁盘、是读还是写、是延迟问题还是吞吐问题。定位方向对了,后面再上其他工具逐层收网就快很多。
提示:做现场诊断的时候,把iostat和pidstat的输出一起记录下来。iostat给的是“磁盘怎么了”的宏观证据,pidstat和iotop给的是“谁弄的”的微观证据,两者一对,定位速度翻倍。
5. 常见问题与排查技巧实录
5.1 %util超过100%正常吗
新版本sysstat在NVMe等支持多队列的设备上,%util可能显示超过100%,比如140%、250%,这并不代表设备出了问题,也不代表它一定就瓶颈了。原因是%util的计算基于设备繁忙时间,多队列设备可以并行处理多个请求,总繁忙时间可能超过采样周期本身,所以百分比会“虚高”。
遇到%util超过100%的情况,别被数字吓到,重点仍然看await和aqu-sz。如果await低、队列不堆积,说明设备虽然繁忙但响应很快,性能还有余量;如果await和队列同时攀升,那不管%util是不是超过100%,都要认真对待了。老内核或老sysstat版本对%util的处理方式不同,有时即使设备很忙也只显示100%,这就是上限了,反而不容易区分。
5.2 多块磁盘设备怎么快速找到瓶颈盘
生产服务器往往挂着好几块盘,sda、sdb、sdc、nvme0n1、nvme0n2铺满一屏。默认情况下iostat会把所有设备都列出来,如果不加-z参数,那些完全空闲的设备也会占用你的视线,找重点盘全靠肉眼扫,效率很低。
我的习惯是加-z参数,只显示有活动的设备,这样空闲盘直接就过滤掉了。如果机器上的盘还是很多,可以用watch -n 1 "iostat -dxk 1 1"做一个自动刷新的仪表盘,每秒钟更新一次,重点盯队列长度和%util最高的那几行。很多实际场景里,只有一块盘在扛所有I/O,其他盘很闲,这种情况下瓶颈盘的定位几乎不需要额外思考。
5.3 与vmstat、sar配合的综合排查思路
iostat虽强,但单独用也有盲区。比如内存不足导致swap换页,这种I/O压力iostat也能看到,但如果你不结合free和vmstat看,就无法判断到底是什么原因触发的。我的综合排查顺序一般是这样:先跑vmstat 1 5看整体状况,看procs的r列、memory的swpd列、cpu的wa列,形成第一印象。然后上iostat -dxk 1 5定位具体设备,判断是哪个盘的读写压力大。再上pidstat -d或iotop定位具体的进程。
比如有一次看到vmstat显示si和so一直在动,换页很频繁,同时iostat显示磁盘%util很高但await正常。这个组合说明问题根因是内存不够导致持续换页,磁盘压力只是结果。如果只看iostat,会误判成磁盘容量不够,方向就错了。所以iostat的最佳定位是“第二棒”,接在vmstat之后缩小范围,而不是唯一的诊断依据。
sar的用处在于回顾历史。如果你怀疑问题发生在半夜某个时间点,但当时没有人在场敲命令,可以直接看sar -d -f /var/log/sysstat/saXX来追溯那个小时的I/O情况,判断是偶发现象还是持续存在。iostat管现场,sar管历史,vmstat管全局,三者互补使用才完整。
5.4 常见问题速查表
| 现象 | 可能原因 | 下一步排查 |
|---|---|---|
| %iowait持续偏高,设备%util不高 | 文件系统锁、内存换页、NFS等网络存储 | 查free、vmstat、dmesg |
| 单块盘%util接近100%,await远大于svctm | 磁盘吞吐饱和,写请求排队 | 用pidstat -d定位进程,考虑拆分I/O |
| %util超过100% | NVMe多队列设备,采样周期内繁忙累计 | 结合await和aqu-sz综合判断 |
| w_await高但r_await正常 | 写路径拥堵,可能是同步刷盘频繁 | 查binlog、redo log落盘策略 |
| 多块盘负载不均 | 数据分布策略问题 | 检查分区、LVM、RAID配置 |
| 设备表出现dm-0等映射设备 | LVM或设备映射器逻辑设备 | 用lsblk找到对应的物理盘 |
另外单独提一个容易被忽略的细节:iostat输出的第一行是系统当前时间,这里的时间格式可能在有些系统上显示不出来,因为时区配置或系统语言环境的问题。做监控记录时最好加上-t参数,让每次采样都带时间戳,这样事后整理数据时不会一头雾水。
用iostat这几个月下来,我最深的感受是:它是个“锚点型”工具,所有I/O问题最后都会在它这里得到确认或排除。很多人习惯一上来就找哪个进程在读写,但不知道整个系统的I/O水位到底什么水平。先用iostat把大盘看明白,再决定要不要继续挖进程,这个顺序能省下大量时间。尤其是那种偶发性的卡顿,等iotop抓出进程时往往已经错过了现场,但iostat留下的采样记录能明确告诉你当时磁盘到底有没有异常。建议所有做Linux性能排查的人都把iostat -dxk练成肌肉记忆,遇到可疑的系统变慢问题,不要犹豫,第一时间先跑一条看看。