pidstat —— 按进程看 CPU、内存、IO、上下文切换

运维工具手册 01-系统监控与性能 4.0 KB 原文

pidstat —— 按进程看 CPU、内存、IO、上下文切换

分类:01 系统监控与性能 适用:Linux(sysstat 包) 一句话:top 只能看 CPU 和内存,pidstat 还能按进程看磁盘 IO、缺页、上下文切换,且输出适合脚本。

1. 它解决什么问题

  • 磁盘 IO 高,但 iostat 只告诉我设备忙,是谁在读写?
  • 内存涨了,是哪个进程在缺页、在换出?
  • 上下文切换异常,是哪个进程在疯狂切?
  • 需要周期性采样并落盘做曲线。

2. 基本用法

pidstat 1                 # 每秒一次,显示所有进程的 CPU
pidstat 1 5               # 每秒一次,共 5 次
pidstat -p 1234 1         # 只看某 PID
pidstat -p ALL 1          # 显式指定所有进程(含无活动的)
pidstat -C nginx 1        # 按命令名过滤(正则)
pidstat -u -p ALL 1       # 只看 CPU(默认就是 -u)
pidstat -h                # 输出带时间戳,便于落盘
pidstat -l                # 显示完整命令行
pidstat -t                # 显示线程级
pidstat -G <group>        # 按进程组
pidstat -U <user>         # 按用户

pidstat 必须带间隔参数才有统计意义,否则只输出累计值。

3. 五类核心指标

3.1 CPU(-u)

pidstat -u 1 5
UID   PID   %usr %system  %guest   %wait    %CPU   CPU  Command
root  1234   12.00    3.00    0.00    0.00   15.00     2  java
列 含义 判读
%usr 用户态 CPU 应用计算
%system 内核态 CPU 系统调用、锁、内存分配
%guest 虚拟机内 CPU KVM 宿主机上才有
%wait 等 CPU 的时间占比 >10% 说明 CPU 竞争激烈,该扩容
%CPU 总占用 单核 100% 为满

%wait 是很多人忽略的黄金指标:进程明明不忙,但一直在排队等 CPU。

3.2 内存(-r)

pidstat -r 1 5
UID  PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
root 1234     12.00      0.00 8123456  912340   5.80  java
列 含义 判读
minflt/s 次缺页(无需 IO) 高但正常,内存分配活跃
majflt/s 主缺页(需读磁盘/swap) 非 0 就是性能问题,说明真缺内存
VSZ 虚拟内存 虚高正常
RSS 常驻内存 真实占用(含共享内存,会重复计)
%MEM 占总内存比

3.3 磁盘 IO(-d)

pidstat -d 1 5
UID  PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
root 1234      0.00   8192.00      0.00      12  mysqld
列 含义 判读
kB_rd/s 每秒读
kB_wr/s 每秒写 找出写盘大户
kB_ccwr/s 被取消的写(脏页被覆盖,未落盘) 高说明写了又改,浪费
iodelay IO 阻塞时钟周期(相对值) 高说明该进程被 IO 拖住

iodelay 单位是 clock ticks,只能横向比较不同进程,不是毫秒。

3.4 上下文切换(-w)

pidstat -w 1 5
UID  PID   cswch/s nvcswch/s  Command
root 1234   1200.00     30.00  java
列 含义 判读
cswch/s 自愿切换(等 IO/锁/信号量) 高 → 锁竞争、IO 等待
nvcswch/s 非自愿切换(时间片用完被抢) 高 → CPU 不足,进程被强制让出

3.5 栈与线程(-s、-t)

pidstat -s 1            # 栈使用(需较新版本)
pidstat -t -p 1234 1    # 该进程的每个线程
pidstat -t -w -p 1234 1 # 线程级上下文切换,找热点线程

4. 实战场景

4.1 找出写盘最多的进程

iostat -x 1 3 /dev/sdb        # 确认 sdb 忙
pidstat -d 1 5 | sort -k5 -nr | head -10

注意 pidstat -d 输出的是所有进程,按 kB_wr/s 排序即可。

4.2 判断是 CPU 不足还是锁竞争

pidstat -u -w -p <PID> 1 10
  • %wait 高 + nvcswch/s 高 → CPU 不够,扩核或降并发。
  • %usr 不高 + cswch/s 很高 → 锁竞争/IO 等待,去看线程栈。

4.3 定位内存泄漏进程

pidstat -r 1 60 > /tmp/mem.log
# 观察 RSS 单调上涨且不回落
awk 'NR>3 {print $2, $7, $8}' /tmp/mem.log | sort -k3 -nr | head

4.4 留证并画曲线

pidstat -h -u -r -d -w -p ALL 5 720 > /tmp/pidstat_$(date +%F).log
# 5 秒一次,采 1 小时,带时间戳

导入 Excel/Grafana 前用 awk 清洗:

grep -v '^#' /tmp/pidstat.log | grep -v '^$' | awk '{print $1,$2,$3,$9,$10}' 

4.5 线程级热点

pidstat -t -u -p <PID> 1 5
# 输出里 TID 列是线程号,配合 top -H 或 jstack 定位代码

5. 常见坑

  1. 不带间隔参数:输出开机以来的累计平均,看起来一切正常,是误判重灾区。
  2. RSS 会重复计算共享内存:多进程共享同一块内存时,每个进程都算一遍,总和可能超过物理内存。精确统计用 smem 的 PSS。
  3. %CPU 单核 100% 上限:多线程进程可超过 100%(如 800%)。
  4. iodelay 不是毫秒:是 clock tick 累计,只适合排序比较。
  5. 线程数过多时输出巨大:加 -p <PID> 或 -C <name> 收窄。
  6. 容器内 -p ALL 看不到宿主机其他进程(PID namespace 隔离),但 %CPU 是相对宿主机的,会偏小。
  7. -C 是正则:-C java 会匹配 javac,写 -C '^java$' 更准。
  8. 老版本无 %wait 列:sysstat 11.5+ 才有,CentOS 7 的 10.1 没有。
  9. 进程消失后 PID 复用:长时间采样脚本要同时记录启动时间(ps -o lstart)。

6. 速查表

pidstat 1                          # CPU,所有进程
pidstat -u -p <PID> 1              # 单进程 CPU
pidstat -r 1                       # 内存
pidstat -d 1                       # 磁盘 IO
pidstat -w 1                       # 上下文切换
pidstat -t -p <PID> 1              # 线程
pidstat -C '^nginx$' 1             # 按命令名
pidstat -h -u -r -d -w 5 720       # 带时间戳长采样

# 关键:%wait 高=CPU 竞争;majflt/s>0=真缺内存;nvcswch/s 高=被抢 CPU
pidstat —— 按进程看 CPU、内存、IO、上下文切换 - 知识库 - 起航社区