Linux 内存与性能监控

Linux 系统中用于监控性能的核心命令行工具,从高层级的系统概览到深入的进程级分析。

第一部分:高层级系统概览

这些工具可以让你快速了解系统的健康状况、运行时间和资源利用率的总体情况。

1. uptime - 快速系统健康检查

uptime 命令是检查系统当前负载和已运行时间的最简单方法。

  • 作用:显示当前时间、系统已运行时长、登录用户数以及过去 1、5、15 分钟的系统平均负载。
  • 目的:快速评估系统是否近期重启过,以及当前是否处于高负载状态。

基本语法与用法

1
uptime

输出示例:

1
14:21:33 up 12 days,  3:42,  2 users,  load average: 0.07, 0.14, 0.11

输出详解

  • **14:21:33**:当前的系统时间。
  • **up 12 days, 3:42**:系统自上次启动以来已运行的总时长。如果时长很短,可能意味着系统发生了意外重启或崩溃。
  • **2 users**:当前登录到系统的用户会话数。
  • **load average: 0.07, 0.14, 0.11**:这是最关键的指标,三个数字分别代表过去 1 分钟、5 分钟、15 分钟的平均负载。
    • 定义:在特定时间段内,处于可运行状态 (Running)不可中断睡眠状态 (Uninterruptible Sleep / Waiting for I/O) 的平均进程数。
    • **解读方法 (结合 CPU 核心数)**:
      1. 首先,通过 nproclscpu 命令获取 CPU 核心数。
      2. Load < 核心数:系统有空闲资源,负载轻松。例如,在 4 核系统上负载为 0.07,表示非常空闲。
      3. Load ≈ 核心数:系统资源已接近饱和。
      4. Load > 核心数:系统已过载,进程需要排队等待 CPU 时间,表明存在性能瓶瓶颈。

常用选项

  • **-p, --pretty**:以更易读的格式显示运行时长。
    1
    2
    uptime -p
    # 输出: up 12 days, 3 hours, 42 minutes
  • **-s, --since**:显示系统启动的确切日期和时间。
    1
    2
    uptime -s
    # 输出: 2025-08-05 10:39:44

底层机制

uptime/proc 虚拟文件系统获取信息:

  • 运行时长来自 /proc/uptime
  • 平均负载来自 /proc/loadavg

2. free - 内存使用快照

free 命令提供了系统物理内存 (RAM) 和交换空间 (Swap) 使用情况的快速摘要。

概念与用途

  • 作用:显示物理内存和交换分区的总量、已用量、空闲量等信息。
  • 目的:快速判断系统内存是否紧张,以及是否过度依赖交换空间。
  • 数据来源:通过解析 /proc/meminfo 文件来提供一个汇总视图。

基本语法与用法

1
free

输出示例 (单位:KB):

1
2
3
              total        used        free      shared  buff/cache   available
Mem: 16389828 8271624 3298320 312312 4829884 7480120
Swap: 2097148 12312 2084836

输出详解

  • **total**:总安装的物理内存或交换空间大小。
  • **used**:已使用的内存。这个值的计算方式是 total - free - buff/cache
  • **free**:完全未被使用的内存。
  • **shared**:被多个进程共享的内存,主要用于 tmpfs 等。
  • buff/cache:被内核用作缓冲区 (buffers)页缓存 (cache) 的内存。Linux 会积极地将空闲内存用于缓存,以加速文件和磁盘 I/O 操作。这部分内存在应用程序需要时可以被立即释放。
  • available这是判断内存压力的最重要指标。它估算了在不发生交换(swapping)的情况下,可供新应用程序使用的内存大小。它约等于 free + 可回收的 buff/cache

核心理念:在 Linux 中,used 内存很大是正常现象,因为“空闲的内存就是浪费的内存”。只要 available 值充足,系统就不算内存紧张。

常用选项

  • -h, --human: 以人类可读的单位 (GB, MB, KB) 显示。这是最常用的选项。

    1
    free -h
  • -b, -k, -m, -g: 分别以字节 (Bytes)、KB、MB、GB 为单位显示。

  • -s N: 每 N 秒刷新一次数据,用于持续监控。

    1
    2
    3
    4
    5
    free -h -s 2
    ```* **`-c N`**: 与 `-s` 配合使用,表示刷新 N 次后退出。
    ```bash
    # 每 2 秒刷新一次,总共刷新 5 次
    free -h -s 2 -c 5

运维实例

  • 判断内存瓶颈:如果 available 的值非常小,并且 Swapused 值持续增加,说明物理内存已不足,系统开始使用硬盘作为虚拟内存,这将严重影响性能。
  • 自动化监控脚本:可以编写脚本,当 available 内存低于某个阈值(如 500MB)时自动报警。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash

# 使用 free -m 获取以MB为单位的内存信息
# 使用 awk 过滤出以 "Mem:" 开头的行
# 打印该行的第 7 个字段 (available 列)
available_mem=$(free -m | awk '/^Mem:/ {print $7}')

# 判断可用内存是否小于 500 MB
if [ "$available_mem" -lt 500 ]; then
# 如果条件成立,发送告警信息
# 实际场景中,这里可以是发送邮件、钉钉或企业微信消息等
echo "Alert: Available memory is low! Currently at ${available_mem}MB."
fi




代码解析

  • free -m: 以 MB 为单位显示内存信息。
  • |: 管道符,将前一个命令的输出作为后一个命令的输入。
  • awk ‘/^Mem:/ {print $7}’: awk 是一个强大的文本处理工具。
    • ‘/^Mem:/‘: 匹配以 “Mem:” 开头的行。
    • {print $7}: 打印该行的第 7 列(字段),在 free -m 的输出中,这通常是 available 列。

可以将这样的脚本加入到 cron 定时任务中,实现周期性的自动内存监控。

第二部分:综合性能监控

这些工具提供了更全面的视图,结合了 CPU、内存、I/O 等多个维度的信息。

3. vmstat - 虚拟内存统计

vmstat (Virtual Memory Statistics) 是一个功能强大的工具,可以报告关于进程、内存、分页、块 I/O、中断和 CPU 活动的信息。

概念与用途

  • 作用:动态地实时显示系统各项资源的运行状态,尤其适用于分析系统是否存在性能瓶颈。
  • 目的:判断系统瓶颈是来自 CPU、内存还是 I/O。

基本语法与用法

1
2
# 每 2 秒刷新一次,共刷新 5 次
vmstat 2 5

输出示例:

1
2
3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 3298320 4829884 7480120 0 0 1 2 101 202 12 3 85 0 0

输出详解

  • procs (进程)
    • r (Run queue): 正在运行或等待 CPU 的进程数。如果这个值长期大于 CPU 核心数,说明 CPU 存在瓶颈。
    • b (Blocked): 处于不可中断睡眠状态的进程数,通常是在等待 I/O。如果这个值较大,可能表示 I/O 瓶颈。
  • memory (内存)
    • swpd: 已使用的交换空间大小 (KB)。
    • free: 空闲的物理内存大小 (KB)。
    • buff: 用于块设备 I/O 的缓冲区大小 (KB)。
    • cache: 用作文件系统缓存的页缓存大小 (KB)。
  • swap (交换)
    • si (Swap In): 每秒从交换空间换入到内存的数据量 (KB/s)。如果该值不为 0,说明内存不足。
    • so (Swap Out): 每秒从内存换出到交换空间的数据量 (KB/s)。如果该值不为 0,说明内存严重不足。
  • io (块设备)
    • bi (Blocks In): 每秒从块设备读取的数据块数 (通常为 KB/s)。
    • bo (Blocks Out): 每秒写入到块设备的数据块数 (通常为 KB/s)。
  • system (系统)
    • in (Interrupts): 每秒的中断次数。
    • cs (Context Switches): 每秒的上下文切换次数。频繁的上下文切换会消耗大量 CPU 时间。
  • cpu (CPU 使用率百分比)
    • us (User): 用户态代码消耗的 CPU 时间百分比。
    • sy (System): 内核态代码消耗的 CPU 时间百分比。如果该值过高,说明系统调用开销大。
    • id (Idle): CPU 空闲时间百分比。
    • wa (Wait I/O): CPU 等待 I/O 完成的时间百分比。如果该值过高,表示 I/O 是系统瓶颈。
    • st (Steal): 在虚拟化环境中,被宿主机 (Hypervisor) 偷走的 CPU 时间百分比。

常用选项

  • -a, --active: 显示活动和非活动内存。
  • -S M: 以 MB 为单位显示内存相关信息。
  • -t, --timestamp: 在每行输出后添加时间戳。
  • -d, --disk: 显示详细的磁盘统计信息。
  • -s, --stats: 显示自系统启动以来的各项事件计数器和内存统计的汇总表。

您提的建议非常好!为 vmstat 补充更多具体的运维场景和实例,能极大地提升这篇指南的实用价值。vmstat 的魅力就在于它能通过几个简单的数字揭示系统层面的复杂问题。

我将完全重写 vmstat 的“运维应用场景”部分,加入多个详细的、分步骤的诊断案例和更具代表性的监控脚本。

实例

vmstat 的输出信息非常密集,是排查系统级性能瓶颈的利器。运维工程师通常通过观察关键指标的变化趋势来诊断问题。

场景一:诊断 CPU 瓶颈

  • 问题现象:应用响应缓慢,top 命令显示总体 CPU 使用率很高,%idle 接近 0。

  • 诊断命令

    1
    2
    # 每秒刷新一次,持续观察
    vmstat 1
  • 关键指标与分析

    1. 观察 procs -> r
      • 分析r 列表示正在运行或等待 CPU 的进程数。如果这个值持续地、显著地大于您的 CPU 核心数(通过 nproc 命令查看),则表明 CPU 已经成为瓶颈,有大量进程在排队等待执行。
    2. 观察 cpu -> ussy
      • 分析
        • 如果 %us (用户态) 长期很高 (例如 > 70%),说明是应用程序本身(如计算密集型任务、死循环)消耗了大量 CPU。
        • 如果 %sy (内核态) 长期很高 (例如 > 30%),说明是内核或系统调用占用了大量 CPU,可能是 I/O 操作频繁、驱动程序问题或系统调用开销过大。
  • 结论与下一步

    • 确认 CPU 瓶颈后,应使用 pidstat -u 1perf top定位具体是哪个进程或函数在消耗 CPU 资源。

场景二:诊断 I/O 瓶颈

  • 问题现象:系统响应迟钝,但 top 显示 CPU 的 %idle 很高,利用率并不饱和。
  • 诊断命令
    1
    vmstat 1
  • 关键指标与分析
    1. 观察 cpu -> wa
      • 分析wa (Wait I/O) 表示 CPU 等待 I/O 操作(通常是磁盘读写)完成的时间百分比。如果这个值持续偏高 (例如 > 20%),强烈暗示系统的瓶颈在 I/O 子系统,CPU 大部分时间都在“无所事事”地等待硬盘响应。
    2. 观察 procs -> b
      • 分析b 列表示被阻塞、等待 I/O 的进程数。如果这个值长期大于 0,也佐证了 I/O 存在瓶颈。
    3. 观察 io -> bibo
      • 分析:这两列显示了块设备(磁盘)的读写活动量。如果 bi (读) 或 bo (写) 的数值很大,说明正有大量的磁盘操作,这与高 %wa 是一致的。
  • 结论与下一步
    • 确认 I/O 瓶颈后,应使用 iostat -x 1iotop定位是哪个磁盘、哪个进程在进行大量的读写操作。

场景三:诊断内存压力与交换活动

  • 问题现象:系统突然变得极度缓慢,甚至 SSH 连接都可能卡顿。
  • 诊断命令
    1
    vmstat 1
  • 关键指标与分析
    1. 观察 swap -> siso
      • 分析si (Swap In) 和 so (Swap Out) 分别表示从磁盘换入内存和从内存换出到磁盘的数据量。只要这两列出现非零值,就必须高度警惕。这表明物理内存已经不足,内核被迫使用速度慢上千倍的硬盘来充当内存。频繁的交换是系统性能的头号杀手。
    2. 观察 memory -> freeswpd
      • 分析free 列的值持续走低,同时 swpd (已用交换空间) 的值在增加,这是内存不足的直接证据。
  • 结论与下一步
    • 确认系统在进行频繁交换后,应立即使用 free -h 查看总体内存情况,并用 pidstat -r 1top(按内存排序)找出消耗内存最多的“罪魁祸首”,考虑优化程序或增加物理内存。

场景四:自动化脚本监控

除了手动排查,vmstat 也常用于自动化监控脚本,对关键指标设置阈值进行告警。

示例:监控系统是否在进行磁盘交换 (Swap Out)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

# 运行 vmstat 1 秒采样 2 次,以获取第二个(瞬时)数据点。
# tail -1 只取最后一行输出。
# awk '{print $8}' 提取第 8 列,即 'so' (swap-out) 列。
swap_out=$(vmstat 1 2 | tail -1 | awk '{print $8}')

# 设置阈值,例如每秒交换出超过 10KB 就告警
threshold=10

if [ "$swap_out" -gt "$threshold" ]; then
# 发送告警
echo "High swap-out activity detected: ${swap_out} KB/s. Memory pressure is critical!"
fi

脚本解析

  • vmstat 1 2: 运行两次的原因是 vmstat 的第一行输出是系统自启动以来的平均值,没有实时参考意义。第二行及以后的输出才是基于采样间隔的瞬时值。
  • 这个脚本可以集成到监控系统中,一旦发现系统开始进行磁盘交换,就能立即触发告警,让运维人员及时介入处理。

4. dstat - 全能的系统资源统计工具

dstat 是一个功能极其丰富的工具,它可以看作是 vmstat, iostat, netstatifstat 等命令的组合体,并增加了许多额外功能。

概念与用途

  • 作用:实时、模块化地监控系统各项资源,包括 CPU、磁盘 I/O、网络、内存分页等。
  • 特点
    • 模块化:可以自由组合要监控的指标。
    • 彩色输出:结果直观,易于阅读。
    • 插件系统:可扩展监控更多应用,如 MySQL、NFS 等。
    • CSV 导出:方便后续进行数据分析和绘图。

基本语法与用法

1
2
# 默认模式,每秒刷新一次
dstat

输出示例:

1
2
3
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read writ| recv send| in out | int csw
3 2 95 0 0| 12k 48k| 0 0 | 18B 42B| 213 450

输出详解 (默认模式)

  • total-cpu-usage: CPU 使用情况 (usr, sys, idl, wai, stl),与 vmstat 类似。
  • dsk/total: 磁盘 I/O 汇总 (read, writ),单位默认为 Bytes。
  • net/total: 网络流量汇总 (recv, send),单位默认为 Bytes。
  • paging: 分页活动 (in=page in, out=page out)。
  • **system**:系统事件 (int=中断, csw=上下文切换)。

常用选项 (模块化组合)

dstat 的强大之处在于通过选项组合监控内容:

  • -c: 显示 CPU 统计 (--cpu)。
  • -m: 显示内存统计 (--mem)。
  • -d: 显示磁盘 I/O 统计 (--disk)。
  • -n: 显示网络统计 (--net)。
  • -l: 显示负载均值 (--load)。
  • -g: 显示分页统计 (--page)。
  • -y: 显示系统统计 (--sys)。
  • --top-cpu: 显示消耗 CPU 最多的进程。
  • --top-io: 显示进行最多 I/O 操作的进程。
  • --output <file.csv>: 将输出结果保存为 CSV 文件。

组合示例:

1
2
3
4
5
# 同时监控 CPU、内存、磁盘和网络,每 2 秒一次,共 10 次
dstat -cmdn 2 10

# 找出消耗 I/O 最多的进程
dstat --top-io

dstat 的最大优势就是其模块化和灵活性,非常适合在运维一线快速、全面地定位问题。

dstat实例

dstat 是运维工程师的“瑞士军刀”,因为它能用一条命令替代多个传统工具,并以高度可读的方式呈现信息。以下是一些典型的实战场景。

场景一:系统性能“全面体检”

这是最常用的场景,用于快速了解系统当前是否存在明显的性能瓶颈。

  • 问题现象:接到报告说“服务器有点慢”,但没有具体指向。

  • 诊断命令

    1
    2
    # 显示最核心的指标:CPU, 磁盘, 网络, 系统负载, 内存
    dstat -cdnlmy

    或者使用一个更紧凑的版本:

    1
    2
    # 每秒刷新,显示 CPU, 磁盘, 网络和系统事件
    dstat -cdnsy 1
  • 分析思路

    1. 看 CPU (-c): wai (I/O 等待) 是否过高?sys (内核态) 是否异常?
    2. 看磁盘 (-d): readwrit 是否有巨大的流量?
    3. 看网络 (-n): recvsend 是否流量饱和或有异常突发?
    4. 看系统 (-y): csw (上下文切换) 是否过高,暗示进程竞争激烈?
    5. 看内存 (-m): used 是否接近 totalfree 是否极低?(虽然 dstat 没有 available 列,但可以初步判断)
  • 结论:通过这一条命令,你可以在几秒钟内对系统的 CPU、磁盘、网络三大瓶颈来源做出初步判断,然后决定下一步使用哪个更专业的工具(如 iostat, pidstat)进行深入分析。

场景二:定位消耗资源最多的“元凶”进程

当系统负载很高时,需要快速找出是哪个进程在消耗资源。

  • 问题现象uptime 显示负载很高,top 看到有进程 CPU 或 I/O 占用率高。
  • 诊断命令
    1
    2
    # 实时显示消耗 CPU、内存和 I/O 最多的进程
    dstat --top-cpu --top-mem --top-io
  • 分析思路
    • --top-cpu: 直接列出当前消耗 CPU 时间最多的进程名和其 CPU 使用率。
    • --top-mem: 列出占用物理内存最多的进程。
    • --top-io: 列出进行最多磁盘 I/O 操作的进程。
  • 结论:这个组合命令几乎可以立即锁定导致系统变慢的“罪魁祸首”,省去了在 topiotophtop 之间来回切换的麻烦。

场景三:分析网络应用与磁盘 I/O 的关联

在处理数据库、Web 服务器或存储服务时,经常需要分析网络流量是否导致了大量的磁盘 I/O。

  • 问题现象:一个文件服务器或数据库服务器,在网络流量增大时,磁盘响应变慢。

  • 诊断命令

    1
    2
    # 同时监控网络流量、TCP 连接数和磁盘的详细 I/O
    dstat -ntd --tcp-states # 有的版本可能是 --tcp

    如果你还想看具体是哪个磁盘分区在忙,可以这样:

    1
    2
    # 监控所有网络接口、TCP 连接状态和 sda1、sdb1 两个分区的 I/O
    dstat -nt --disk-util sda1,sdb1 2
  • 分析思路

    • 观察关联性:当网络 recvsend 流量 (-n) 飙升时,磁盘的 readwrit (-d) 是否也随之飙升?
    • **观察 TCP 状态 (--tcp-states)**:EST (Established) 连接数是否异常增多?TMW (Time Wait) 状态是否过多,占用了大量端口资源?
  • 结论:通过这种方式,可以直观地看到网络请求和后端存储压力之间的因果关系,对于优化应用缓存、调整网络参数非常有帮助。

场景四:数据采集与事后分析

当需要对一个长时间运行的任务进行性能分析,或者需要向他人提供性能报告时,dstat 的 CSV 导出功能非常有用。

  • 问题现象:需要对一个数据迁移任务(持续数小时)的资源消耗情况进行记录,以便后续制作性能图表。

  • 诊断命令

    1
    2
    3
    4
    # 每 10 秒采样一次,持续采集 360 次(即 1 小时)
    # 监控 CPU, 内存, 磁盘, 网络, 负载,并添加时间戳
    # 结果输出到 report.csv 文件中
    dstat -cdnmly --time --output /tmp/report.csv 10 360
  • 分析思路

    1. 任务运行期间,让脚本在后台执行。
    2. 任务结束后,report.csv 文件就是一个标准的 CSV 格式文件。
    3. 你可以用 Excel、Google Sheets、Python (Pandas) 或 Gnuplot 等工具导入这个文件,轻松地绘制出 CPU 使用率、磁盘 I/O 流量等随时间变化的曲线图。
  • 结论dstat 不仅是实时诊断工具,也是一个轻量级的数据采集器,非常适合性能基准测试和报告制作。

通过这些具体的、组合式的实例,可以看出 dstat 在实际运维工作中的强大灵活性和高效性。它真正做到了“一器在手,全局我有”。

第三部分:专项深度分析

当发现某个特定领域(如 I/O 或 CPU)存在问题时,可以使用这些专业工具进行深入分析。

5. iostat - 磁盘 I/O 性能分析

iostat (Input/Output Statistics) 专注于监控系统的磁盘 I/O 子系统和 CPU 使用率。

概念与用途

  • 作用:提供详细的块设备 (磁盘) I/O 活动和 CPU 统计。
  • 目的:定位磁盘性能瓶颈,分析数据库、文件服务器等 I/O 密集型应用的性能问题。
  • 来源:属于 sysstat 软件包,可能需要手动安装 (sudo apt install sysstat)。

基本语法与用法

1
2
# 每 2 秒刷新一次,显示扩展统计信息
iostat -x 2

输出示例 (使用 -x 选项):

1
2
3
4
5
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
2.50 0.00 1.50 10.00 0.00 86.00

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 5.00 10.00 100.00 200.00 0.00 0.00 0.00 0.00 1.20 0.80 0.01 20.00 20.00 0.50 1.00

输出详解

  • avg-cpu 部分

    • %user:用户态 CPU 占用(应用程序消耗 CPU 时间)
    • %nice:被调整优先级 (nice) 的进程消耗 CPU
    • %system:内核态 CPU 占用(系统调用、驱动等)
    • %iowait:CPU 空闲,但在等待 I/O 完成。这是 iostat 中最需要关注的 CPU 指标。如果该值持续偏高,说明磁盘可能是系统的主要瓶颈。
    • %steal:虚拟化环境下,被 hypervisor 占用的 CPU 时间
    • %idle:CPU 空闲时间(不做事、也不等 I/O)
  • Device 部分(磁盘指标,设备 I/O 部分 - 使用 -x 扩展模式)

    读写速率

    • r/s:每秒读请求数(读 IOPS)
    • rkB/s:每秒读数据量(KB/s)
    • w/s:每秒写请求数(写 IOPS)
    • wkB/s:每秒写数据量(KB/s)
    • d/s:每秒 discard 请求数(主要用于 SSD)
    • dkB/s:每秒 discard 数据量

    请求合并

    • rrqm/s:每秒被合并的读请求数
    • %rrqm:被合并的读请求百分比
    • wrqm/s:每秒被合并的写请求数
    • %wrqm:被合并的写请求百分比
    • drqm/s:每秒被合并的 discard 请求数
    • %drqm:被合并的 discard 请求百分比

    等待时间与请求大小

    • r_await:平均读请求等待时间(ms,含排队+执行)
    • rareq-sz:平均每次读请求大小(KB)
    • w_await:平均写请求等待时间(ms)
    • wareq-sz:平均每次写请求大小(KB)
    • d_await:平均 discard 请求等待时间
    • dareq-sz:平均 discard 请求大小
    • f/s:每秒 flush 请求数(文件系统落盘)
    • f_await:flush 请求平均等待时间

    队列与利用率

    • aqu-sz:平均 I/O 队列长度
    • %util:磁盘利用率,接近 100% 表示磁盘已满负荷

iostat 是诊断磁盘 I/O 性能问题的绝对主力工具。

iostat 命令行参数详解

iostat 的参数可以分为几类:控制输出内容、控制输出格式和控制采样方式。

基本语法: iostat [选项] [间隔秒数] [次数]

1. 控制输出内容的选项

  • -c: (CPU)

    • 单独显示 CPU 使用率统计报告。默认情况下,iostat 会同时显示 CPU 和设备信息,使用此选项可以只关注 CPU。
  • -d: (Device)

    • 单独显示块设备(磁盘)的使用率统计报告。
  • -N: (Network Filesystem)

    • 显示网络文件系统 (NFS) 的统计信息。
  • -h: (Human-readable)

    • 以人类可读的格式(例如 K, M, G)显示输出。这个选项非常实用,可以避免去数零。
  • -k: (Kilobytes)

    • 以 KB 为单位显示统计数据(这是默认值)。
  • -m: (Megabytes)

    • 以 MB 为单位显示统计数据。
  • -p [device | ALL]: (Partition)

    • 显示块设备及其所有分区的统计信息。你可以指定某个设备(如 -p sda)或使用 ALL 显示所有设备及其分区。
  • -x: (Extended)

    • 这是 iostat 最重要、最常用的选项! 它会显示一组扩展的、更详细的 I/O 统计信息,包括 await, svctm, aqu-sz, %util 等诊断性能瓶颈的关键指标。强烈建议始终带上 -x 参数
  • -z: (Zero suppress)

    • 在报告中省略那些在采样周期内没有任何活动的设备。这可以让输出更简洁,尤其是在系统挂载了大量空闲设备时。

2. 控制输出格式的选项

  • -t: (Timestamp)

    • 在每行输出前打印时间戳。这对于记录和分析长时间的性能数据非常有用。
  • -y: (Yes, skip first report)

    • 禁止打印第一次的统计报告。iostat 的第一次报告是自系统启动以来的平均值,通常参考意义不大,我们更关心的是实时的、基于采样间隔的瞬时值。使用 -y 可以让输出更干净。

3. 控制采样方式的参数

  • [interval]: 采样间隔(秒)。例如 iostat 2 表示每 2 秒刷新一次。
  • [count]: 采样次数。例如 iostat 2 5 表示每 2 秒刷新一次,总共刷新 5 次后退出。如果省略 countiostat 将会持续运行。

iostat 实例

掌握了参数后,我们来看如何在实际运维中组合使用它们来解决问题。

场景一:快速诊断系统是否存在 I/O 瓶颈

这是最基础也是最核心的用法,用于判断系统变慢是否由磁盘 I/O 引起。

  • 问题现象:应用响应缓慢,但 top 显示 CPU 空闲率 (%id) 很高。
  • 诊断命令
    1
    2
    # 每 2 秒刷新一次,显示扩展统计信息和时间戳
    iostat -x -t 2
  • 分析思路(重点观察以下指标)
    1. %iowait (CPU 部分):
      • 如果这个值**持续高于 20%**,说明 CPU 大量时间都在等待 I/O,磁盘是性能瓶颈的重大嫌疑对象。
    2. %util (设备部分):
      • 磁盘利用率。如果这个值**持续接近 100%**,表明该磁盘已经饱和,无法处理更多的 I/O 请求,是系统的瓶颈点。
    3. r_await / w_await (设备部分):
      • 读/写请求的平均等待时间(毫秒)。这个值包含了请求在队列中的等待时间和磁盘实际处理请求的时间。
      • 经验法则:对于机械硬盘 (HDD),如果 await 时间持续超过 20ms,性能可能已经较差。对于固态硬盘 (SSD),这个值应该远低于 1ms,如果持续超过 5ms 就需要警惕。
    4. aqu-sz (设备部分):
      • 平均请求队列长度。如果这个值持续大于 1,说明到达的 I/O 请求速率超过了磁盘的处理能力,请求开始排队。
  • 结论:如果同时观察到高 %iowait、高 %util、高 await 和不断增长的 aqu-sz,就可以100% 确定磁盘 I/O 是系统瓶颈

场景二:分析数据库服务器的读写负载模式

  • 问题现象:需要优化一个 MySQL 数据库的性能,首先要了解它的 I/O 模式是读密集型还是写密集型。
  • 诊断命令
    1
    2
    # 监控承载数据库文件的磁盘分区(例如 sdb1),以 MB 为单位显示,持续观察
    iostat -x -m -p sdb1 1
  • 分析思路
    1. 比较 rMB/swMB/s:
      • 如果 rMB/s (每秒读 MB 数) 远大于 wMB/s,说明数据库主要是执行查询操作,是读密集型。优化方向可能是增加缓存、优化索引、使用读写分离等。
      • 如果 wMB/s 远大于 rMB/s,说明主要是执行插入、更新、删除操作,是写密集型。优化方向可能是优化事务、使用更高性能的 SSD、调整日志写入策略等。
    2. 比较 r/sw/s:
      • 这两列表示每秒的读写请求次数。结合上面的吞吐量,可以分析 I/O 的大小。例如,如果 wMB/s 很高,但 w/s 相对较低,说明应用正在执行大块的顺序写入。反之,如果 w/s 很高,但 wMB/s 不高,说明是大量的小文件随机写入。

场景三:评估新硬件或配置变更的效果

  • 问题现象:将数据库从 HDD 迁移到 SSD,或者调整了文件系统挂载参数后,需要量化评估性能提升了多少。
  • **诊断方法 (基准测试)**:
    1. 变更前: 在业务高峰期,使用 iostat -x -t 1 300 > before.log 采集 5 分钟的性能数据。
    2. 变更后: 在相同的业务高峰期,使用 iostat -x -t 1 300 > after.log 再次采集 5 分钟数据。
    3. 对比分析:
      • 比较两个日志文件中关键指标的平均值峰值
      • 主要看 r_await, w_await, svctm 是否有显著下降。例如,从 HDD 的 10ms 下降到 SSD 的 0.1ms,这就是巨大的性能提升。
      • 同时,在相同的负载下,%util 是否显著降低,aqu-sz 是否不再积压。

场景四:监控并找出“坏邻居”

  • 问题现象:在一台虚拟化宿主机或共享存储上,某个虚拟机或应用突然性能下降,怀疑是其他“邻居”的 I/O 操作干扰所致。
  • 诊断命令
    1
    2
    # 在宿主机上,显示所有设备及其分区的统计信息,并省略空闲设备
    iostat -x -p ALL -z 1
  • 分析思路
    • 通过此命令,你可以看到宿主机上所有挂载的逻辑卷或磁盘分区。
    • 观察是哪个设备 (dm-X, sdX) 的 %util 异常高,并且 r/sw/s 流量巨大。
    • 一旦定位到繁忙的设备,就可以根据虚拟化平台的管理工具或系统配置,反向追查这个设备属于哪个虚拟机,从而找到制造大量 I/O 的“坏邻居”。

运维实战场景

  • 判断磁盘瓶颈:观察 %utilr_awaitw_await。如果 %util 长期高于 80%,且 await 时间很长(例如超过 10ms),说明磁盘 I/O 性能已达瓶颈。
  • 分析读写模式:通过 r/sw/s 的比例,可以判断应用是读密集型还是写密集型。

iostat -x 实际样例 + 分析逻辑

📌 样例输出

1
2
3
4
5
6
7
8
$ iostat -x -p sda 2 3
Linux 6.8.0-71-generic (mug) 08/19/2025 _x86_64_ (4 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
12.50 0.00 4.00 8.00 0.00 75.50

Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz aqu-sz %util
sda 200.00 16384.00 5.00 2.44 15.2 82.0 150.00 20480.00 3.00 1.96 22.5 136.5 5.5 98.0

📊 分析逻辑

  • CPU 部分

    • %iowait = 8.00
      → CPU 有 8% 的时间在等磁盘,说明 I/O 是瓶颈。
    • %idle = 75.50
      → CPU 其实很空闲,问题不在 CPU。
  • 读写速率

    • r/s = 200rkB/s = 16384
      → 每秒 200 次读请求,总吞吐 16 MB/s。
    • w/s = 150wkB/s = 20480
      → 每秒 150 次写请求,总吞吐 20 MB/s。
      👉 说明磁盘在同时处理读写操作。
  • 等待时间

    • r_await = 15.2 ms
      → 平均每个读请求要等 15 毫秒,这偏高(机械盘正常 5~15ms,SSD 应该 <1ms)。
    • w_await = 22.5 ms
      → 写请求平均要等 22 毫秒,也比较慢。
  • 队列和利用率

    • aqu-sz = 5.5
      → 平均有 5.5 个请求在排队。
    • %util = 98.0
      → 磁盘几乎满负荷工作。

🧭 判断结论

  • 这是 I/O 瓶颈,不是 CPU 瓶颈。
  • 请求响应时间高、队列长度长、%util 接近 100%,说明磁盘被打满。
  • 如果这是 SSD → 性能异常(可能有写放大或固件问题)。
  • 如果是 HDD → 属于正常瓶颈,需要增加磁盘或用 SSD。
  • 对于数据库类应用,IOPS 和延迟比吞吐量更关键。

🔑 快速判断口诀

  • %util

    • <70% → 磁盘比较轻松

    • 70–90% → 磁盘有压力

    • 90% → 磁盘已饱和

  • await

    • HDD 正常几 ms 到十几 ms
    • SSD 应该 <1ms,如果 >5ms 就有问题
  • aqu-sz

    • 越大说明队列越长,I/O 堵车
  • %iowait

    • 如果 CPU 大部分时间在等 I/O,说明瓶颈不在 CPU

6. sar - 全能的系统活动报告器

sar (System Activity Reporter) 是 Linux 下最全面的性能分析工具之一,它最大的特点是不仅能实时监控,还能收集和报告历史性能数据。

概念与用途

  • 作用:全面收集、报告和保存系统的各项活动信息,包括 CPU、内存、I/O、网络、进程等。
  • 目的:进行长期性能趋势分析、故障排查和容量规划。
  • 核心优势历史数据分析能力sysstat 包会通过定时任务 (cron) 自动收集数据,默认保存在 /var/log/sa/ 目录下。

基本语法与用法

1
2
3
4
5
# 实时监控:每 1 秒采样一次 CPU 使用情况,共 5 次
sar -u 1 5

# 读取历史数据:查看当天(假设是17号)的网络统计历史
sar -n DEV -f /var/log/sa/sa17

常用监控维度 (选项)

  • CPU 使用率 (-u): 显示 %user, %system, %iowait, %idle 等。

  • 内存和分页 (-r, -B):

    • -r: 报告内存利用率 (kbmemfree, kbmemused, %memused)。
    • -B: 报告分页统计 (pgpgin/s 换入, pgpgout/s 换出)。
  • 块设备 I/O (-d):

    • 报告 tps (每秒传输次数), rd_sec/s (每秒读扇区数), wr_sec/s (每秒写扇区数)。
  • 网络统计 (-n):

    • sar -n DEV: 报告网络接口流量 (rxpck/s 收包, txpck/s 发包, rxkB/s, txkB/s)。

      sar 本身 没有直接提供选项来指定单一设备。它会把所有接口的统计都输出。

      但是可以结合 管道过滤 来只看特定设备,比如:

      sar -n DEV 2 5 | grep eth0

      sar -n DEV 2 | egrep 'IFACE|eth0|wlan0'

    • sar -n TCP: 报告 TCP 连接统计 (active/s 主动连接, passive/s 被动连接)。

  • 进程和上下文切换 (-w, -q):

    • -w: 报告任务创建 (proc/s) 和上下文切换 (cswch/s)。
    • -q: 报告运行队列长度 (runq-sz) 和平均负载 (ldavg-1, ldavg-5, ldavg-15)。

sar 常用参数速查

  • CPU 相关

    • -u:CPU 使用率统计(用户、系统、iowait、idle 等)

    • -P ALL:显示所有 CPU 的使用情况

    • -P <cpu>:指定某个 CPU

  • 内存

    • -r:内存统计(free, used, buffers, cache)

    • -R:内存页面换入换出(pgpgin/s, pgpgout/s)

    • -B:分页统计(pgfault/s, pgmajfault/s)

    • -H:HugePages 使用情况

  • I/O / 磁盘

    • -b:I/O 传输速率统计(tps, rtps, wtps, bread/s, bwrtn/s)

    • -d:块设备统计(读写次数、吞吐量)

    • -p <dev>:指定磁盘设备(配合 -d

    • -q:队列长度和平均负载

    • -F [MOUNT]:文件系统统计

  • 网络

    • -n DEV:网络接口统计(rxpck/s, txpck/s, rxkB/s, txkB/s 等)

    • -n EDEV:网络接口错误统计

    • -n TCP:TCP 协议统计(active/s, passive/s 等)

    • -n ETCP:TCP 错误统计(retrans/s, orsts/s 等)

    • -n SOCK:套接字使用情况

  • 电源 / 硬件监控

    • -m CPU:CPU 实时主频

    • -m FREQ:CPU 平均主频

    • -m FAN:风扇转速

    • -m TEMP:设备温度

    • -m IN:电压输入

    • -m USB:USB 设备

  • 任务 / 进程

    • -w:上下文切换和系统调用统计

    • -W:swap 统计(swapin/s, swapout/s)

    • -q:运行队列长度、负载统计

    • -f:显示自开机以来 fork 数

    • -o <file>:将数据保存到二进制文件

  • 其他

    • -v:inode、文件和其他内核表的统计

    • -I SUM:中断统计(所有 CPU 汇总)

    • -I ALL:每个中断的详细统计

    • -I <n>:指定中断号

    • -s [hh:mm:ss]:开始时间

    • -e [hh:mm:ss]:结束时间

    • -i <sec>:间隔时间

    • -h:更友好格式显示大数值


⚡ 使用模式示例:

  • 实时采样:sar -u 2 5 → 每 2 秒刷新一次,共采集 5 次 CPU 使用率
  • 历史数据:sar -r -f /var/log/sa/sa10 → 查看第 10 天的内存历史数据

要不要我帮你把这些参数再整理成 不同场景下的常用组合命令(比如排查 CPU 瓶颈、I/O 瓶颈、网络瓶颈的常见 sar 用法)?

运维场景

  • 排查夜间性能问题:服务器在凌晨 3 点变慢,但白天无法复现。运维人员可以通过 sar -u -f /var/log/sa/sa<日期> 来查看当时 CPU 的 %iowait 是否异常升高,从而定位问题。
  • 容量规划:通过分析过去一个月的 sar 网络流量数据 (-n DEV),可以预测未来的带宽需求。

sar 最强大的地方在于其历史数据追溯能力,这使它成为事后故障分析、性能趋势预测和容量规划的无价之宝。

sysstat 包默认会通过 cron 或 systemd timer 每 10 分钟对系统进行一次快照采样,并将数据以二进制格式保存在 /var/log/sa/ 目录下,文件名通常是 saDDDD 代表日期,如 sa17 代表 17 号的数据)。还有一个人类可读的文本汇总报告 sarDD

sar 实例

场景一:事后故障分析 - “服务器昨天半夜为什么那么卡?”

这是 sar 最经典的用途。白天无法复现的问题,可以通过回溯历史日志来定位。

  • 问题现象:用户报告昨晚(假设是 16 号)凌晨 2 点到 3 点之间,应用访问极度缓慢,但现在已经恢复正常。

  • 诊断步骤

    1. 第一步:检查总体负载和 CPU

      • 命令
        1
        2
        3
        4
        # -q: 查看负载和队列长度
        # -f: 指定历史日志文件
        # -s, -e: 指定开始和结束时间
        sar -q -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00
      • 分析:查看 ldavg-1 (1分钟负载) 在该时间段是否远超 CPU 核心数。如果负载很高,再看是 CPU 还是 I/O 问题。
        1
        2
        # -u: 查看 CPU 使用情况
        sar -u -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00
      • 分析
        • 如果 %user%system 很高,说明是 CPU 密集型任务,可能是某个定时脚本或批处理任务触发了。
        • 如果 %iowait 很高,说明瓶颈在 I/O,CPU 在等待磁盘。
    2. 第二步:深入分析 I/O 瓶颈 (如果上一步发现 %iowait 高)

      • 命令
        1
        2
        3
        # -d: 查看磁盘活动
        # -p: 美化设备名,更易读
        sar -d -p -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00
      • 分析:查看哪个设备 (DEV) 的 %util 在该时段接近 100%,并且 await (平均等待时间) 异常高。这通常是由夜间的备份任务、数据同步或日志归档引起的。
    3. 第三步:检查内存和交换活动

      • 命令
        1
        2
        3
        # -r: 查看内存使用
        # -S: 查看交换空间使用
        sar -rS -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00
      • 分析:查看 %memused 是否接近 100%,以及 kbswpout/s (换出到 swap 的速率) 是否有非零值。如果发现有大量的交换活动,说明当时物理内存被耗尽,可能是某个内存泄漏的应用或计划任务导致的。
  • 结论:通过这一系列的回溯查询,即使问题已经消失,运维人员也能准确定位故障根源是 CPU 密集任务、磁盘 I/O 瓶颈还是内存耗尽,从而进行针对性的优化。

场景二:性能趋势分析与容量规划

sar 记录的长期数据是进行容量规划的宝贵财富。

  • 问题现象:业务量持续增长,需要评估当前服务器资源(CPU、内存、网络)何时会达到瓶颈,以便提前采购和扩容。

  • 诊断步骤

    1. 分析 CPU 使用率的长期趋势

      • 目标:找出业务高峰期(例如工作日下午 2 点到 4 点)的 CPU 平均使用率,并观察其月度变化。
      • 脚本示例 (分析过去一周的数据):
        1
        2
        3
        4
        5
        6
        for day in $(seq -w $(date -d "7 days ago" +%d) $(date +%d)); do
        echo "--- Analyzing CPU for day ${day} ---"
        sar -u -f /var/log/sa/sa${day} -s 14:00:00 -e 16:00:00 | \
        grep 'Average:' | \
        awk '{print "Avg %user:", $3, "Avg %system:", $5, "Avg %idle:", $8}'
        done
      • 分析:将每天高峰期的 CPU 使用率(特别是 %idle 的反面)记录下来,制作成图表。如果发现空闲率 (%idle) 逐周稳定下降,例如从 40% -> 30% -> 20%,就可以预测出大约在几周后 CPU 资源将耗尽。
    2. 分析网络带宽使用情况

      • 目标:评估当前网络出口带宽是否足够。
      • 命令
        1
        2
        3
        4
        5
        6
        7
        # -n DEV: 查看网络接口流量
        # 分析过去一个月所有日期的 sar 日志
        find /var/log/sa/ -name 'sa*' -mtime -30 -exec sar -n DEV -f {} + | \
        grep 'Average:' | \
        grep 'eth0' | \
        awk '{print "rxkB/s:", $5, "txkB/s:", $6}' | \
        sort -k4 -nr | head -n 5
      • 分析:这个命令会找出过去 30 天内,eth0 网卡在业务高峰期平均发送流量 (txkB/s) 最高的 5 个记录。通过这些峰值数据,你可以判断当前带宽利用率是否已经接近签约带宽的 80%,从而决定是否需要升级带宽。

场景三:健康巡检与基线建立

为服务器建立性能基线,是快速发现异常的前提。

  • 问题现象:如何判断服务器当前的性能表现是“正常”还是“异常”?
  • 方法
    1. 建立基线: 在系统运行平稳、业务正常的时期,收集一周的 sar 数据作为基线。
      1
      2
      3
      4
      # 汇总过去 7 天每天的 CPU 平均使用情况
      sar -u -f $(ls /var/log/sa/sa* | tail -n 7) | grep 'Average:'
      # 汇总过去 7 天每天的磁盘平均 I/O 情况
      sar -d -p -f $(ls /var/log/sa/sa* | tail -n 7) | grep 'Average:'
    2. 日常巡检: 编写一个脚本,每天自动运行 sar 获取前一天的性能摘要,并与已建立的基线进行对比。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      # 获取昨天的 CPU %iowait 平均值
      yesterday_iowait=$(sar -u -f /var/log/sa/sa$(date -d "1 day ago" +%d) | grep 'Average:' | awk '{print $6}')

      # 假设基线 iowait 不应超过 5.0
      baseline_iowait=5.0

      if (( $(echo "$yesterday_iowait > $baseline_iowait" | bc -l) )); then
      echo "Warning: Yesterday's average iowait (${yesterday_iowait}%) is above baseline (${baseline_iowait}%)!"
      fi
  • 结论:通过建立性能基线,任何偏离正常范围的指标都会被快速识别出来,实现了从“被动救火”到“主动预防”的转变。

sar 的精髓在于它赋予了运维人员“时间旅行”的能力,能够将瞬时的性能问题放在一个长期的时间维度里去审视,从而发现问题的根本原因和未来趋势。

7. pidstat - 进程级性能监控利器

pidstat 专注于监控单个进程或线程的资源使用情况,是 topps 的强大补充。

概念与用途

  • 作用:实时、详细地显示指定进程或所有进程的 CPU、内存、I/O、上下文切换等资源使用情况。
  • 目的:精确定位是哪个进程或线程导致了系统资源消耗过高。

基本语法与用法

1
2
# 每 2 秒监控一次所有进程的 CPU 使用情况
pidstat -u 2

核心监控维度 (选项)

  • CPU (-u):
    • %usr: 进程在用户空间消耗的 CPU 百分比。
    • %system: 进程在内核空间消耗的 CPU 百分比。
    • %CPU: 进程总的 CPU 使用率。
  • 内存 (-r):
    • minflt/s: 每秒次要缺页错误次数 (不涉及磁盘 I/O)。
    • majflt/s: 每秒主要缺页错误次数 (需要从磁盘加载内存页)。该值过高表示内存压力大。
    • VSZ: 虚拟内存大小 (KB)。
    • RSS: 常驻内存大小 (KB),即进程实际占用的物理内存。持续增长可能意味着内存泄漏。
  • 磁盘 I/O (-d):
    • kB_rd/s: 进程每秒从磁盘读取的数据量。
    • kB_wr/s: 进程每秒向磁盘写入的数据量。
    • kB_ccwr/s: 进程取消的写操作数据量。
  • 上下文切换 (-w):
    • cswch/s: 每秒自愿上下文切换次数 (如等待资源)。
    • nvcswch/s: 每秒非自愿上下文切换次数 (如时间片用完被强制调度)。该值过高说明 CPU 竞争激烈。
  • 线程级监控 (-t):
    • 此选项会额外显示每个线程 (TID/LWP) 的统计信息,对于分析多线程应用(如 Java)非常有用。
  • 指定进程 (-p <PID>):
    • pidstat -p 1234 -urd 1:每秒监控 PID 为 1234 的进程的 CPU、内存和 I/O。

运维实战场景

  • 定位高 CPU 消耗的 Java 线程
    1. top -H -p <java_pid> 找到消耗 CPU 最高的线程 ID (LWP)。
    2. pidstat -t -p <java_pid> -u 1 确认该 LWP 的 CPU 占用。
    3. 将 LWP 转换为十六进制,并使用 jstack 打印 Java 堆栈,找到对应的 Java 线程,从而定位到问题代码。
  • 找出疯狂写日志的进程
    • 运行 pidstat -d 1,观察哪个进程的 kB_wr/s 异常高。

好的,我们来系统地拆解 pidstat 命令。这是一个非常精细化的工具,能将性能监控的粒度从整个系统下沉到具体的进程线程,是精准定位资源消耗“元凶”的利器。


pidstat 命令详解

pidstatsysstat 工具集的一员,专注于按进程提供详细的资源使用报告。

基本语法: pidstat [选项] [间隔秒数] [次数]

1. 核心功能选项 (按监控维度分类)

这些选项决定了 pidstat 监控哪一类资源,它们可以组合使用。

  • -u: (CPU) - 默认选项

    • 报告进程的 CPU 使用统计。
    • 关键列
      • %usr: 进程在用户空间(执行应用程序代码)消耗的 CPU 百分比。
      • %system: 进程在内核空间(执行系统调用)消耗的 CPU 百分比。
      • %guest: 进程在虚拟机中运行 guest 代码的 CPU 百分比。
      • %CPU: 进程总的 CPU 使用率。注意:在多核系统上,这个值可以超过 100%。例如,250% 表示该进程用满了 2.5 个 CPU核心。
  • -r: (Memory / Page Faults)

    • 报告进程的内存使用和缺页错误统计。
    • 关键列
      • minflt/s: 每秒次要缺页错误 (minor fault)。这意味着进程需要的内存在物理内存中,但需要内核为其建立页表映射。这个值较高通常是正常的。
      • majflt/s: 每秒主要缺页错误 (major fault)。这意味着进程需要的内存页已经不在物理内存中(可能被换出到磁盘了),需要从磁盘重新加载。这个值持续不为零,是内存压力大的明确信号
      • VSZ: 虚拟内存大小 (Virtual Size),单位 KB。
      • RSS: 常驻内存大小 (Resident Set Size),单位 KB。这是进程当前实际占用的物理内存大小。如果一个进程的 RSS 持续增长而不下降,可能存在内存泄漏。
  • -d: (Disk I/O)

    • 报告进程的磁盘 I/O 统计。
    • 关键列
      • kB_rd/s: 进程每秒从磁盘读取的数据量 (KB)。
      • kB_wr/s: 进程每秒向磁盘写入的数据量 (KB)。
      • kB_ccwr/s: 进程取消的写操作数据量 (KB)。当进程向页缓存写入,但随后又截断文件时会发生。
      • 注意:这个统计只包括真正的磁盘 I/O,不包括通过文件系统缓存的读写。
  • -w: (Context Switches)

    • 报告进程的上下文切换统计。
    • 关键列
      • cswch/s: 每秒自愿上下文切换 (voluntary context switches)。通常发生在进程因为等待资源(如 I/O、锁)而主动放弃 CPU 时。
      • nvcswch/s: 每秒非自愿上下文切换 (non-voluntary context switches)。发生在进程的 CPU 时间片用完,被操作系统调度器强制剥夺 CPU 时。这个值持续很高,说明 CPU 竞争非常激烈
  • -t: (Threads)

    • 这是一个增强选项,可以与其他功能选项(如 -u, -r)配合使用。它会显示进程下的所有线程的统计信息,而不仅仅是主进程。
    • 关键列
      • TGID: 主进程的 ID (Thread Group ID)。
      • TID/LWP: 线程的真实 ID (Light Weight Process)。

2. 控制输出对象的选项

  • -p <PID> | ALL: (Process ID)

    • 指定要监控的进程 ID。你可以用逗号分隔多个 PID (如 -p 1234,5678)。
    • 使用 ALL 关键字表示监控所有当前活动的进程。
  • -C <command_string>: (Command)

    • 监控命令名中包含指定字符串的进程。例如 -C java 会监控所有包含 “java” 字符串的进程。
  • -U <user_name>: (User)

    • 只监控指定用户拥有的进程。

3. 控制输出格式的选项

  • -h: (Human-readable / Horizontal)

    • 在一个易于阅读的水平格式中显示所有统计信息,而不是默认的多行格式。
  • -I: (I/O class)

    • -d 模式下,显示 I/O 优先级(如果有的话)。
  • -l: (Long format)

    • 显示更长的进程名或命令行。

pidstat 实例

pidstat 的威力在于组合使用这些选项,进行精准打击。

场景一:找出哪个进程在“吃”CPU

  • 问题现象topuptime 显示系统 CPU 使用率很高。
  • 诊断命令
    1
    2
    3
    4
    5
    # 每 2 秒执行一次 "pidstat -u | sort -k8 -nr | head -n 20"
    watch -n 2 "pidstat -u | sort -k9 -nr | head -n 20"

    # 每 2 秒执行一次 "pidstat -u 1 1" (采样间隔1秒, 次数1次)
    watch -n 2 "pidstat -u 1 1 | tail -n +4 | sort -k9 -nr | head -n 20"
  • 分析思路
    • 这个命令会动态地将 CPU 占用最高的进程排在最前面。
    • 观察 %CPU 列,如果某个进程持续占用一个或多个核心(例如 nginx 占用 400%),就找到了元凶。
    • 同时观察 %usr%system 的比例。如果 %usr 高,是应用逻辑问题;如果 %system 高,是系统调用(如频繁 I/O)问题。

场景二:定位 Java 应用中高 CPU 占用的具体线程

这是 pidstat 最经典的“杀手级”应用之一。

  • 问题现象:一个 Java 服务进程 CPU 占用 100% 或更高,需要定位到是哪段代码出了问题。
  • 诊断步骤
    1. 找到 Java 进程的 PID: pgrep java
    2. pidstat 监控该进程的所有线程:
      1
      2
      # 假设 Java 进程 PID 是 1234
      pidstat -u -p 1234 -t 1
    3. 找出 CPU 最高的线程 ID (TID/LWP): 在输出中,找到 %CPU 最高的那个线程,记下它的 TID 列的值,例如 1255
    4. 将 TID 转换为十六进制:
      1
      2
      printf "%x\n" 1255
      # 输出: 4e7
    5. 使用 jstack 打印 Java 堆栈并查找该线程:
      1
      jstack 1234 | grep '0x4e7' -A 30
  • 结论jstack 的输出会精确地告诉你这个 nid=0x4e7 的线程当前正在执行哪一个 Java 类、哪一个方法。至此,问题代码就完全暴露了。

场景三:诊断“磁盘很忙,但不知道是谁干的”

  • 问题现象iostat 显示 sda 磁盘的 %util 接近 100%,但需要知道是哪个进程导致的。
  • 诊断命令
    1
    2
    # 每 2 秒刷新一次,显示所有进程的 I/O 情况
    pidstat -d 2
    或者使用 iotop 的替代方案:
    1
    2
    # 持续监控,按写入速率排序
    pidstat -d 1 | sort -k5 -nr
  • 分析思路
    • 观察 kB_rd/skB_wr/s 列。哪个进程的这两列数值最大,就是 I/O 压力的制造者。
    • 这对于找出正在疯狂写日志的应用、正在进行大量数据读写的数据库,或者失控的备份脚本非常有效。

场景四:分析是否存在内存泄漏

  • 问题现象:一个长期运行的服务,其内存占用似乎在不断缓慢增长。
  • 诊断命令
    1
    2
    # 每 30 秒采样一次,持续监控指定进程的内存使用
    pidstat -r -p <PID> 30
  • 分析思路
    • 将输出重定向到一个文件,长时间观察 RSS (实际物理内存) 列的变化趋势。
    • 如果 RSS 的值在没有业务高峰的情况下,呈现出“只增不减”或“阶梯式增长且从不回落”的趋势,那么该进程有很高的内存泄漏嫌疑。
    • 同时,如果 majflt/s (主要缺页错误) 偶尔出现,也佐证了物理内存可能不足,部分内存被换出。

pidstat 就像一个手术刀,能帮助运维工程师在复杂的系统中,精确地剖析出每一个进程的资源消耗细节,是从系统级监控走向应用级诊断的关键桥梁。

8. perf - 终极性能分析神器

perf 常用子命令:

perf stat:收集整体性能计数器(CPU cycles, instructions, cache-misses 等)

perf record:采样收集事件信息,生成 perf.data 文件

perf report:分析 perf.data 文件,展示热点函数

perf top:实时显示性能热点(类似 top

perf trace:跟踪系统调用(类似 strace,但更高效)

perf list:显示所有可用的事件

perf sched:调度器相关分析(perf sched latency, perf sched map 等)

perf annotate:展示函数源码级别的热点

perf mem:内存访问分析(load/store latency 等)

perf 是 Linux 内核自带的性能分析工具,功能极其强大,能够深入到硬件、内核和应用程序函数级别进行分析。

概念与用途

  • 作用:通过采样 CPU 的性能监控单元 (PMU, Performance Monitoring Unit) 和内核事件 (tracepoints),分析程序和系统的性能瓶颈。
  • 目的:定位到消耗 CPU 的具体函数、分析缓存命中率、分支预测失败率等底层硬件事件。常用于生成**火焰图 (Flame Graphs)**。

核心子命令

perf 通过子命令来执行不同任务:

  • perf list: 列出当前系统支持的所有可测量事件。

  • perf stat: 运行一个命令,并统计其运行期间的性能数据摘要。

    1
    2
    perf stat ls
    # 输出包括指令数、时钟周期、IPC (每周期指令数)、缓存未命中等。
  • perf top: 类似于 top,但实时显示消耗 CPU 最多的函数(包括内核函数和用户函数)。这是快速定位热点函数的利器。

    1
    sudo perf top
  • perf record: 采样并记录性能数据,生成一个 perf.data 文件,用于后续分析。

    1
    2
    # 对整个系统进行采样,频率为 99Hz,并记录调用栈
    sudo perf record -F 99 -a -g -- sleep 10
  • perf report: 读取并分析 perf.data 文件,以交互式界面的形式展示函数的热点分布。

火焰图生成流程

火焰图是可视化性能瓶颈的强大工具。

  1. 采集数据: perf record -F 99 -p <PID> -g -- sleep 30
  2. 生成脚本输入: perf script > out.perf
  3. 折叠堆栈: stackcollapse-perf.pl out.perf > out.folded (需要从 FlameGraph 项目获取脚本)
  4. 生成 SVG 图片: flamegraph.pl out.folded > kernel.svg
  5. 在浏览器中打开 kernel.svg,图中宽度越宽的函数,表示它消耗的 CPU 时间越多。

总结

perf 是高级性能工程师和内核开发者的必备工具,它提供了其他工具无法比拟的深度和广度,是解决复杂性能问题的最终手段。

perf,这无疑是 Linux 性能分析工具箱中的“核武器”。它非常强大,但也相对复杂。

perf - Linux 性能事件分析神器

一、perf 概念

  • 全称:Performance Events for Linux
  • 作用perf 不是一个单一的工具,而是一个工具集。它利用 Linux 内核的 perf_events 子系统,能够访问 CPU 的性能监控单元 (PMU, Performance Monitoring Unit) 和内核中的**跟踪点 (tracepoints)**,从而对软件和硬件的性能进行极其深入的分析。
  • 分析层次
    • 硬件层面:CPU 周期、指令数、缓存未命中 (Cache Misses)、分支预测失败 (Branch Misses) 等。这些是衡量 CPU 执行效率的底层指标。
    • 内核层面:系统调用、上下文切换、缺页中断、调度器事件等。
    • 应用层面:找出用户态应用程序中消耗 CPU 最多的热点函数
  • 核心优势
    • 内核集成:作为内核的一部分,开销较低,数据更精确。
    • 全景视图:能够同时分析用户代码和内核代码的性能,打通应用和系统之间的壁垒。
    • 事件驱动:可以基于非常丰富的性能事件进行采样。
    • 火焰图 (Flame Graph) 的主要数据来源。

二、安装 perf

perf 通常不随系统默认安装,需要根据你的内核版本来安装对应的工具包。

  • 对于 Debian/Ubuntu 系统:
    1
    2
    3
    # $(uname -r) 会自动获取当前的内核版本号
    sudo apt update
    sudo apt install linux-tools-common linux-tools-$(uname -r)
  • 对于 RHEL/CentOS 系统:
    1
    sudo yum install perf
  • 验证安装:
    1
    perf --version

三、perf 核心子命令与用法

perf 的功能是通过一系列子命令来实现的。

1. perf list - 查看可用的性能事件

在开始分析之前,先了解你的系统支持哪些事件。

  • 用法
    1
    perf list
  • 输出解读
    • Hardware Event: PMU 提供的硬件事件,如 cycles, instructions, cache-misses
    • Software Event: 内核提供的软件事件,如 context-switches, page-faults
    • Tracepoint Event: 内核代码中预设的跟踪点,覆盖了系统调用的进入/退出、调度器的决策、网络包的收发等海量细节。例如 syscalls:sys_enter_openat

2. perf stat - 性能数据“体检”

对一个命令(或整个系统)进行一次快速的性能统计,给出摘要报告。

  • 用法
    • 分析单个命令:
      1
      2
      # 运行 `ls -R /` 命令,并统计其性能数据
      perf stat ls -R / >/dev/null
    • 监控正在运行的进程:
      1
      2
      # 监控 PID 为 1234 的进程,持续 5 秒
      perf stat -p 1234 sleep 5
    • 监控整个系统:
      1
      2
      # 监控整个系统 5 秒
      sudo perf stat -a sleep 5
  • 关键输出指标
    • task-clock (msec): 任务实际占用的 CPU 时间。
    • context-switches: 上下文切换次数。
    • cycles: 消耗的 CPU 时钟周期数。
    • instructions: 执行的指令数。
    • IPC (instructions per cycle): 非常重要的指标! 每个 CPU 周期执行的指令数。值越高,说明 CPU 的流水线效率越高,程序对 CPU 的利用越好。如果 IPC 很低(例如 < 1.0),可能意味着大量的缓存未命中或分支预测失败,导致 CPU 频繁等待。
    • cache-misses: 缓存未命中次数。
    • branch-misses: 分支预测失败次数。

3. perf top - 实时热点函数分析器

类似 top,但它显示的是当前消耗 CPU 最多的函数,而不是进程。

  • 用法
    1
    2
    # 需要 root 权限来分析整个系统
    sudo perf top
  • 交互界面
    • Overhead: 函数消耗 CPU 时间的百分比。
    • Symbol: 函数名。
    • Shared Object: 函数所在的库或可执行文件(例如 [kernel.kallsyms] 表示内核函数)。
  • 常用选项
    • -p <PID>: 只分析指定进程。
    • -e <event>: 按指定事件(如 cache-misses)来排序,找出缓存未命中率最高的函数。

4. perf record & perf report - 离线深度分析

这是 perf 最强大的用法,用于采样、记录,然后进行详细的离线分析。

  • 工作流程

    1. perf record (记录): 对目标进行性能事件采样,并将结果保存到 perf.data 文件中。
    2. perf report (报告): 读取 perf.data 文件,以交互式的方式展示热点分析结果。
  • 用法示例

    1
    2
    3
    4
    5
    6
    7
    8
    # 1. 记录系统范围的 CPU 采样数据 10 秒钟
    # -F 99: 采样频率为 99Hz (每秒 99 次)
    # -a: System-wide,监控所有 CPU
    # -g: 记录函数的调用图 (call graph),对分析函数调用关系至关重要
    sudo perf record -F 99 -a -g -- sleep 10

    # 2. 分析生成的 perf.data 文件
    perf report
  • perf report 交互界面

    • 主界面按百分比显示热点函数。
    • 选中一个函数按回车,可以展开其调用栈,看到是谁调用了它 (callers) 以及它调用了谁 (callees)。
    • a 可以在函数和源码级别之间切换(需要调试符号)。

perf 实战应用场景

场景一:快速定位导致 CPU 100% 的“元凶”函数

  • 问题现象top 显示某个应用进程 CPU 占用率持续 100%。
  • 诊断步骤
    1. 找到进程 PID: pgrep my_app (假设 PID 为 2345)。

    2. 实时定位热点:

      1
      sudo perf top -p 2345
      • perf top 的输出中,排在第一行的函数就是当前最消耗 CPU 的函数。这通常能直接定位到问题代码(比如一个死循环或一个计算密集的算法)。
    3. 如果问题复杂,进行离线分析:

      1
      2
      3
      4
      5
      # 对该进程进行 15 秒的调用图采样
      sudo perf record -p 2345 -g -- sleep 15

      # 分析报告
      perf report
      • perf report 中,你可以详细地追溯调用链,理解为什么这个热点函数会被如此频繁地调用。

场景二:生成火焰图,可视化性能瓶颈

火焰图是分析 CPU 性能的终极利器,而 perf 是其主要的数据来源。

  • 问题现象:需要直观地向开发人员展示复杂应用的性能瓶颈所在。
  • 操作流程
    1. 安装火焰图工具:
      1
      2
      git clone https://github.com/brendangregg/FlameGraph.git
      cd FlameGraph
    2. 使用 perf record 采集数据 (必须带 -g):
      1
      sudo perf record -F 99 -a -g -- sleep 30
    3. 生成火焰图:
      1
      2
      3
      4
      5
      6
      # 将 perf.data 转换为可读的堆栈信息
      sudo perf script > out.perf

      # 使用火焰图工具的脚本进行折叠和绘图
      ./stackcollapse-perf.pl ../out.perf > ../out.folded
      ./flamegraph.pl ../out.folded > ../myserver.svg
  • 结果分析
    • 用浏览器打开生成的 myserver.svg 文件。
    • 火焰图的横轴代表 CPU 占用时间,“平顶”越宽的函数,就意味着它本身消耗了越多的 CPU 时间,是直接的性能瓶颈。
    • 火焰图的纵轴代表函数调用栈的深度。
    • 这是一个极其直观的工具,能让复杂的性能问题一目了然。

场景三:分析程序为何运行缓慢 (IPC 过低)

  • 问题现象:程序运行缓慢,但 CPU 使用率并未跑满,怀疑是内存访问或分支预测效率低下。
  • 诊断步骤
    1. 使用 perf stat 进行“体检”:

      1
      perf stat -e cycles,instructions,cache-misses,branch-misses ./my_slow_program
    2. 分析指标

      • 计算 IPC: 用 instructions 除以 cycles。如果 IPC 值非常低(例如 < 0.5),说明 CPU 大部分时间都在等待,而不是在执行指令。
      • 分析原因: 查看 cache-missesbranch-misses 的比例。
        • 如果缓存未命中率高,说明程序的数据访问模式不友好,导致频繁从慢速的主存中读取数据。优化方向是改善数据局部性(Data Locality)。
        • 如果分支预测失败率高,说明代码中存在大量难以预测的条件分支(if/else, switch),打乱了 CPU 的指令流水线。优化方向是重构代码逻辑,减少分支。

perf 是一个专业且深入的工具,初次接触可能会觉得复杂。建议从 perf statperf top 开始,熟练后再深入使用 perf record 和火焰图,它将成为你解决性能问题的最强有力的武器。

服务器性能评估的思路与步骤

掌握工具只是第一步,更重要的是形成一套行之有效的方法论。我将它总结为**”三步走”**策略,它能帮你从纷繁复杂的数据中找出问题的根源。

第一步:宏观概览(Broad View)

目标:快速判断问题出在哪个子系统,是 CPU、内存、磁盘还是网络。

  1. 观察系统平均负载(topuptime:负载值是否高于 CPU 核心数?如果高于,说明系统有大量的任务在排队等待执行。
  2. 检查 CPU 状态(vmstat
    • r:CPU 密集型任务过多。
    • wa:I/O 密集型任务过多,需要排查磁盘或网络。
  3. 检查内存状态(vmstatfree
    • si/so:内存不足,正在频繁使用交换区。
  4. 检查网络状态(netstatss:是否有大量的网络连接处于异常状态?

结论:通过这一步,你应该能得到一个初步的结论:比如,“这台服务器的瓶颈似乎在 I/O”或者“问题出在 CPU 资源不足”。

第二步:聚焦排查(Drill Down)

目标:在确定了问题子系统后,精确找到是哪个进程哪个设备哪个网络连接导致了问题。

  1. CPU 问题:使用 tophtop,按 CPU 使用率排序(%CPU),找出是哪个进程消耗了最多的 CPU 资源。然后可以继续用 strace 等工具来跟踪该进程的系统调用。
  2. I/O 问题
    • 磁盘:使用 iostat -x,找出 %util 接近 100% 的磁盘。
    • 网络:使用 netstatss,结合 tcpdump 等抓包工具,分析网络流量和连接状态。
  3. 内存问题:使用 top 找到内存占用最高的进程。如果进程占用内存合理,但整体内存不足,可能需要增加物理内存或优化应用程序配置。

结论:这一步让你从“系统有瓶颈”的模糊概念,转变为“**Nginx 进程占用了 80% 的 CPU,并且 /dev/sdb 磁盘的使用率达到了 98%**”这样的具体问题。

第三步:解决与验证(Solve & Verify)

目标:针对发现的具体问题,采取行动并验证效果。

  1. 解决
    • CPU 瓶颈:优化代码,增加服务器核心,或调整负载均衡。
    • I/O 瓶颈:优化数据库索引,升级到 SSD,或增加磁盘阵列。
    • 内存瓶颈:增加内存,优化应用程序内存配置,或配置缓存。
  2. 验证:在采取措施后,重新使用第一步和第二步的工具进行观察。如果 vmstatr 值降下来了,或者 iostat%util 下降了,那么你的优化就起作用了。

这套方法论就像医生看病一样:先问诊(宏观概览),再做检查(聚焦排查),最后开药(解决与验证)。它能确保你不会盲目地修改配置,而是基于数据做出理性的决策。

现在,你是否对这套思路有了更清晰的了解?或者,你有没有在工作中遇到过某个具体的性能问题,我们可以一起按照这套思路来分析一下?