FIO (Flexible I/O Tester) 综合使用手册 ← 返回

FIO (Flexible I/O Tester) 综合使用手册

版本: v1.0 | 最后更新: 2026-05-27 | 作者: Jens Axboe (FIO), 整理自 CSDN pansaky + RV Script Generator

1. 概述

1.1 什么是 FIO

FIO (Flexible I/O Tester) 是由 Jens Axboe 开发的 Linux 下最强大的磁盘 I/O 性能测试工具。它支持 13 种 I/O 引擎,可通过 Job File 或命令行精确控制测试参数,是服务器硬件验证 (RV Test) 中测量 IOPS、带宽和延迟的标准工具。

1.2 核心能力

- 13 种 I/O 引擎: sync, psync, libaio, mmap, splice, sg, net, cpuio, guasi, rbd, gfapi, fusionsound, rdma - Job File 模式: INI 风格配置文件,支持多 Job 并发 - 丰富的测试模式: 随机/顺序读写、混合读写、TRIM 等 - 精确时延统计: clat (完成延迟), slat (提交延迟), lat (总延迟) - 内置日志与绘图: bandwidth/iops/latency 日志 + fio_generate_plots 自动绘图 - 数据校验: md5, crc32, sha256 等多种校验模式 - 多客户端: --server / --client 模式支持分布式测试

1.3 与其他工具对比

工具 特点 适用场景
dd 简单顺序读写 快速单次测试
FIO 全面可配置,支持多种模式 精细化性能验证
IOMeter Windows 为主,GUI 界面 Windows 平台
Vdbench Java 实现,企业级 存储系统验收

2. 目录结构

2.1 FIO 文件夹结构

FIO/
├── FIO.docx                              # FIO+IPMI 安装 SOP
├── FIO脚本参数.docx                       # Job File 格式说明
├── FIO是测试IOPS的非常好的工具.docx        # 综合教程 (~650行)
├── README-FIO.md                         # 本文档
├── fio-2.1.7-1.el6.rf.x86_64.rpm        # EL6 RPM 包
├── fio-3.7-2.el7.x86_64.rpm             # EL7 RPM 包
├── fio-3.19-3.el8.x86_64.rpm            # EL8 RPM 包
├── fio-2.1.7.tar.bz2                     # 源码包 v2.1.7
└── fio-3.7.tar.gz                        # 源码包 v3.7

2.2 RV Script Generator 目录结构

RV Script Generator/
├── RV Script Generator.py                # 主程序 (2359 行, Python/Tkinter)
├── RV Script Generator.txt               # 说明文档
├── RV Script Generator.exe               # PyInstaller 打包的可执行文件
├── IPMItool命令大全.txt                   # IPMI 风扇控制命令参考
├── image/                                # 图标资源
│   ├── RV Script.png
│   └── RV_Script_Generator.ico
├── test/                                 # FIO 配置模板 (10个)
│   ├── randread-4k-1-16-85%-none
│   ├── randwrite-4k-1-16-85%-none
│   ├── read-128k-1-16-85%-none
│   ├── write-128k-1-16-85%-none
│   ├── read-256k-1-16-85%-none
│   ├── write-256k-1-16-85%-none
│   ├── read-64k-1-16-85%-none
│   ├── write-64k-1-16-85%-none
│   ├── read-1M-1-16-85%-none
│   └── write-1M-1-16-85%-none
├── build/                                # PyInstaller 构建产物
└── dist/                                 # 打包输出
    └── RV_Script_Generator.exe

3. 下载路径

3.1 官方源码下载

FIO 官方发布地址为 kernel.dk:

# 下载最新版本 (替换版本号)
wget http://brick.kernel.dk/snaps/fio-3.12.tar.gz

# 历史版本示例
wget http://brick.kernel.dk/snaps/fio-2.2.5.tar.gz
wget http://brick.kernel.dk/snaps/fio-3.7.tar.gz

3.2 Git 仓库

# 官方 Git
git clone git://git.kernel.dk/fio.git

# GitHub 镜像
git clone https://github.com/axboe/fio.git

3.3 YUM / DNF 安装 (RHEL/CentOS/Fedora)

# EPEL 仓库中的 FIO
yum install fio -y          # CentOS/RHEL 7
dnf install fio -y          # CentOS/RHEL 8+ / Fedora

3.4 APT 安装 (Debian/Ubuntu)

apt-get install fio -y

3.5 本地 RPM 包📁 本地下载

提示:点击按钮将打开网络文件夹,点击即可下载

本目录提供三个版本的 RPM 包,可直接使用:

文件 适用系统 FIO 版本
fio-2.1.7-1.el6.rf.x86_64.rpm RHEL/CentOS 6.x (EL6) 2.1.7
fio-3.7-2.el7.x86_64.rpm RHEL/CentOS 7.x (EL7) 3.7
fio-3.19-3.el8.x86_64.rpm RHEL/CentOS 8.x (EL8) 3.19

3.6 本地源码包

文件 版本 格式
fio-2.1.7.tar.bz2 2.1.7 bzip2
fio-3.7.tar.gz 3.7 gzip

4. 安装说明

4.1 RPM 安装

# 方法一: 直接 rpm 安装
rpm -ivh fio-3.7-2.el7.x86_64.rpm

# 方法二: yum localinstall (自动处理依赖)
yum localinstall fio-3.7-2.el7.x86_64.rpm -y

验证安装:

fio --version
# 输出示例: fio-3.7

4.2 源码编译安装

4.2.1 安装依赖

# CentOS/RHEL
yum install gcc make libaio-devel zlib-devel -y

# Debian/Ubuntu
apt-get install build-essential libaio-dev zlib1g-dev -y

4.2.2 编译步骤

# 解压
tar -zxvf fio-3.7.tar.gz         # .tar.gz 格式
# 或
tar -jxvf fio-2.1.7.tar.bz2      # .tar.bz2 格式

# 进入目录
cd fio-3.7

# 配置 (默认选项)
./configure

# 编译
make -j$(nproc)

# 安装
make install

4.2.3 configure 常用选项

./configure --prefix=/usr/local    # 指定安装路径
./configure --enable-gfio          # 启用 GFIO 图形界面
./configure --disable-native       # 禁用本地优化

4.2.4 验证安装

fio --version                      # 版本号
which fio                          # 安装路径
fio --help                         # 帮助信息

4.3 GFIO 图形界面安装

GFIO 是 FIO 的 GTK2 图形前端,适合不熟悉命令行的用户。

4.3.1 安装 GTK2 依赖

# CentOS/RHEL
yum install gtk2 gtk2-devel cairo-devel -y

# Debian/Ubuntu
apt-get install libgtk2.0-dev libcairo2-dev -y

4.3.2 编译带 GFIO 的 FIO

cd fio-3.7
./configure --enable-gfio
make -j$(nproc)
make install

4.3.3 启动 GFIO

gfio &

4.4 测试安装

# 简单随机读测试 (文件模式)
fio --name=test --rw=randread --bs=4k --size=100M --filename=/tmp/fio_test

# 完成后清理
rm /tmp/fio_test

5. 命令行参数

5.1 基本参数

参数 说明 示例
--name Job 名称 --name=test1
--filename 目标文件或设备 --filename=/dev/sda
--rw 读写模式 --rw=randread
--bs 块大小 --bs=4k
--size 每个 Job 的 I/O 总量 --size=1G
--ioengine I/O 引擎 --ioengine=libaio

5.2 读写模式 (--rw)

说明
read 顺序读
write 顺序写
randread 随机读
randwrite 随机写
rw / readwrite 混合顺序读写
randrw 混合随机读写
trim / randtrim TRIM (仅 SSD)

混合读写比例控制:

--rw=randrw --rwmixread=70    # 70% 读, 30% 写

5.3 IO 引擎 (--ioengine)

FIO 支持 13 种 I/O 引擎,适配不同场景:

引擎 说明 特点
sync 基本同步 I/O read/write 系统调用
psync 基本同步 pread/pwrite positional sync I/O
libaio Linux 原生异步 I/O 推荐用于磁盘测试
mmap 内存映射 I/O 文件映射到内存
splice splice/vmsplice 零拷贝 I/O
sg SCSI generic SCSI 设备
net 网络 I/O 测试网络存储
cpuio CPU 压力 纯 CPU 负载
guasi GUASI 引擎 自定义用户空间异步
rbd Ceph RADOS 块设备 Ceph 存储
gfapi GlusterFS API Gluster 存储
fusionsound Fusion-io 设备 特定硬件

注意事项:

- libaio 在 CentOS 上需安装 libaio-devel - sync 在多 Job 时受限于单线程 - 裸设备测试建议用 libaio + direct=1

5.4 块大小 (--bs)

--bs=4k      # 模拟数据库小 IO
--bs=128k    # 模拟大文件顺序读写
--bs=1M      # 最大吞吐量测试
--bs=4k,8k   # 混合块大小
--bsrange=512-4k  # 块大小范围 (随机)

5.5 队列深度与并发 (--iodepth, --numjobs)

--iodepth=16      # 队列深度 (单 Job 内并发 IO 数)
--numjobs=4       # 并行 Job 数

关键公式: 总并发 IO 数 = numjobs × iodepth

# 4 个 Job, 每个 iodepth=16 → 总并发 64
fio --name=test --rw=randread --bs=4k --numjobs=4 --iodepth=16 ...

# 单 Job 高队列深度 (模拟数据库)
fio --name=test --rw=randread --bs=4k --numjobs=1 --iodepth=32 ...

5.6 时间控制

参数 说明 示例
--runtime 运行时长 (秒) --runtime=300
--ramp_time 预热时间 (不纳入统计) --ramp_time=30
--time_based 基于时间运行 (忽略 --size) 必须与 --runtime 配合
# 运行 5 分钟, 前 30 秒预热
fio --name=test --rw=randread --bs=4k --runtime=300 --ramp_time=30 --time_based ...

5.7 数据控制

参数 说明 示例
--direct 绕过页缓存 (O_DIRECT) --direct=1
--buffered 使用页缓存 (默认) --buffered=1
--sync 同步写入 (O_SYNC) --sync=1
--fsync 每次写入后 fsync --fsync=1
--norandommap 不记录随机位置 --norandommap
--randrepeat 随机序列可重复 --randrepeat=0
--refill_buffers 每次提交后重新填充缓冲区 --refill_buffers
--end_fsync 测试结束后 fsync --end_fsync=1
# 典型裸盘测试配置
--direct=1 --norandommap --randrepeat=0

5.8 校验参数

--verify=md5                              # MD5 校验
--verify=crc32c                           # CRC32C 校验
--verify=sha256                           # SHA256 校验
--verify_fatal=1                          # 校验失败直接退出
--verify_async=1                          # 异步校验 (提高性能)
--verify_backlog=120                      # 异步校验队列深度

5.9 速率限制

--rate=100M             # 限制带宽为 100MB/s
--rate_iops=5000        # 限制 IOPS 为 5000

5.10 CPU 绑定

--cpus_allowed=0-3      # 绑定到 CPU 0-3
--cpus_allowed_policy=split   # 为每个 Job 分配不同 CPU
--numa_cpu_nodes=0      # 绑定 NUMA Node 0
--numa_mem_policy=local # 使用本地内存分配

5.11 日志参数

参数 说明
--write_bw_log 记录带宽日志
--write_iops_log 记录 IOPS 日志
--write_lat_log 记录延迟日志
--log_avg_msec 日志采样间隔 (毫秒)
--write_bw_log=result_bw        # → result_bw_bw.1.log
--write_iops_log=result_iops    # → result_iops_iops.1.log
--write_lat_log=result_lat      # → result_lat_lat.1.log
--log_avg_msec=1000             # 每秒采样一次

5.12 输出控制

参数 说明
--output 输出到文件
--output-format 输出格式 (normal, json, json+, terse)
--group_reporting 汇总所有 Job 结果
--eta 显示预计剩余时间
--eta-newline ETA 进度更新模式

5.13 其他常用参数

参数 说明
--thinktime 每次 IO 间等待 (微秒)
--thinktime_spin 自旋等待 (替代 sleep)
--loops 循环执行次数
--thread 使用 pthread 替代 fork
--invalidate 使能缓存失效
--fsync_on_close 关闭文件前 fsync
--stonewall / --wait_for_all 多 Job 等待控制
--exitall 任一 Job 完成后退出所有
--create_only=1 仅创建文件不测试
--create_serialize=0 并行创建文件
--fadvise_hint 内核预读提示 (0=random, 1=sequential)
--random_distribution 随机分布 (random, zipf, pareto)

6. Job File 格式

6.1 基本格式

FIO Job File 使用 INI 风格的配置语法,以 [section] 开头:

[global]
; 全局参数,对所有 Job 生效
ioengine=libaio
direct=1

[job1]
; Job 特定参数,可覆盖 global
filename=/dev/sda
rw=randread

6.2 Global 段详解

[global] 段定义的参数会被所有后续 Job 继承,避免重复配置:

[global]
ioengine=libaio          # I/O 引擎
direct=1                 # O_DIRECT, 绕过缓存
buffered=0               # 不使用缓存
norandommap              # 不记录随机 I/O 偏移
randrepeat=0             # 随机种子不可重复
refill_buffers           # 每次 IO 后重新填充缓冲区
rw=randread              # 读写模式
bs=4k                    # 块大小
numjobs=1                # 并行 Job 数
iodepth=16               # 队列深度
runtime=120              # 运行时长 (秒)
ramp_time=30             # 预热时间 (秒)
time_based               # 基于时间而非数据量
#loops=1                 # 循环次数 (注释掉表示不循环)

6.3 Device 段详解

每个磁盘设备作为独立 Job 段,命名规则: [sd{letter}-{test_name}-params]

[sda-randread-4k-1-16-85%-none]
filename=/dev/sda                     # 目标设备
size=85%                              # 测试 85% 容量
write_bw_log=/root/rv_test/result/dev/sda/sda-randread-4k-1-16-85%-none-log1
write_iops_log=/root/rv_test/result/dev/sda/sda-randread-4k-1-16-85%-none-log2
write_lat_log=/root/rv_test/result/dev/sda/sda-randread-4k-1-16-85%-none-log3
log_avg_msec=1000                     # 日志采样间隔 1s

命名规则解析: 以 sda-randread-4k-1-16-85%-none 为例: - sda: 设备名 (/dev/sda) - randread: 随机读测试 - 4k: 块大小 - 1: numjobs=1 - 16: iodepth=16 - 85%: 测试 85% 容量 - none: 无特殊标记 (非分组)

6.4 完整示例: 多设备配置

#Config File for randread-4k-1-16-85%-none
[global]
ioengine=libaio
direct=1
buffered=0
norandommap
randrepeat=0
refill_buffers
rw=randread
bs=4k
numjobs=1
iodepth=16
runtime=120
ramp_time=30
time_based

[sda-randread-4k-1-16-85%-none]
filename=/dev/sda
size=85%
write_bw_log=/root/rv_test/result/dev/sda/sda-randread-4k-1-16-85%-none-log1
write_iops_log=/root/rv_test/result/dev/sda/sda-randread-4k-1-16-85%-none-log2
write_lat_log=/root/rv_test/result/dev/sda/sda-randread-4k-1-16-85%-none-log3
log_avg_msec=1000

[sdb-randread-4k-1-16-85%-none]
filename=/dev/sdb
size=85%
write_bw_log=/root/rv_test/result/dev/sdb/sdb-randread-4k-1-16-85%-none-log1
write_iops_log=/root/rv_test/result/dev/sdb/sdb-randread-4k-1-16-85%-none-log2
write_lat_log=/root/rv_test/result/dev/sdb/sdb-randread-4k-1-16-85%-none-log3
log_avg_msec=1000
; ... 继续 sdc, sdd, sde ... 直到 sdx

6.5 参数继承规则

  1. [global] 参数被所有 Job 继承
  2. Job 段中定义的同名参数覆盖 global
  3. 未在 Job 段中定义的参数取 global 值
  4. filename 必须每个 Job 单独指定

7. 测试类型

7.1 4K 随机读写

最常见的小块随机 IO 测试,衡量存储设备的 IOPS 性能。

rw=randread            # 或 randwrite
bs=4k
iodepth=16             # 或 32

用途: 数据库 OLTP 场景模拟、SSD 最大 IOPS 测试

命令行快捷方式:

# 4K 随机读
fio --name=4k-randread --filename=/dev/sda --rw=randread --bs=4k --ioengine=libaio --direct=1 --iodepth=16 --numjobs=1 --runtime=120 --time_based

# 4K 随机写
fio --name=4k-randwrite --filename=/dev/sda --rw=randwrite --bs=4k --ioengine=libaio --direct=1 --iodepth=16 --numjobs=1 --runtime=120 --time_based

7.2 128K 顺序读写

大块顺序 IO,衡量最大吞吐量。

rw=read                # 或 write
bs=128k
iodepth=16

用途: 大文件传输、视频流、备份场景

7.3 256K 顺序读写

rw=read                # 或 write
bs=256k
iodepth=16

7.4 64K 顺序读写

rw=read                # 或 write
bs=64k
iodepth=16

7.5 1M 顺序读写

最大块大小测试,追求峰值带宽。

rw=read                # 或 write
bs=1M
iodepth=16

7.6 混合读写

rw=randrw
rwmixread=70           # 70% 读, 30% 写
bs=4k
iodepth=16

7.7 RV Script Generator 测试类型预设

工具内置 10 种测试类型模板:

分组 测试名称 rw bs tc iodepth runtime
4K Random randread-4k randread 4k iops 16 120
4K Random randwrite-4k randwrite 4k bw 16 120
128K Sequential read-128k read 128k iops 16 120
128K Sequential write-128k write 128k bw 16 120
256K Sequential read-256k read 256k iops 16 120
256K Sequential write-256k write 256k bw 16 120
64K Sequential read-64k read 64k iops 16 120
64K Sequential write-64k write 64k bw 16 120
1M Sequential read-1M read 1M iops 16 120
1M Sequential write-1M write 1M bw 16 120

其中 tc 字段: iops 表示结果提取 IOPS 值, bw 表示结果提取带宽值。


8. 结果分析与可视化

8.1 实时输出解读

FIO 运行结束后的标准输出示例:

test: (g=0): rw=randread, bs=4K-4K/4K-4K, ioengine=libaio, iodepth=16
fio-3.7
Starting 1 process
Jobs: 1 (f=1): [r] [100.0% done] [525.6MB/s] [134k] [r=0,w=0]
...
Run status group 0 (all jobs):
   READ: bw=528MiB/s (553MB/s), 528MiB/s-528MiB/s (553MB/s-553MB/s), io=15.5GiB (16.6GB), run=30045-30045msec

关键指标: - bw: 带宽 (MiB/s, MB/s) - IOPS: 后面显示的 [134k] 表示每秒 134,000 IO - io: 总传输量 - run: 实际运行时间 (ms)

详细时延统计:

clat (usec): min=13, max=1234, avg=45.21, stdev=12.34
lat (usec): min=14, max=1240, avg=46.10, stdev=12.50

- clat: 完成延迟 (Completion Latency) — 提交到完成的时间 - slat: 提交延迟 (Submission Latency) — 发起请求到提交的时间 - lat: 总延迟 (Total Latency) = slat + clat

8.2 日志文件格式

FIO 生成的三类日志文件均为 CSV 格式:

Bandwidth Log (bw_log)

timestamp_ms, bandwidth_bytes, direction
1000, 268435456, 0
2000, 271581184, 0
...

IOPS Log (iops_log)

timestamp_ms, iops, direction
1000, 65536, 0
2000, 66304, 0
...

Latency Log (lat_log)

timestamp_ms, latency_usec, direction, data_size
1000, 45, 0, 4096
2000, 42, 0, 4096
...

8.3 fio_generate_plots

FIO 自带的绘图脚本,需要 gnuplot:

# 1. 运行 FIO 生成日志
fio --name=test --rw=randread --bs=4k --size=1G \
    --write_bw_log=result --write_iops_log=result --write_lat_log=result \
    --log_avg_msec=1000

# 2. 使用 fio_generate_plots 绘图
fio_generate_plots result /path/to/output/dir

# 输出文件:
#   result_bw.svg
#   result_iops.svg
#   result_clat.svg
#   result_slat.svg
#   result_lat.svg

8.4 fio2gnuplot

更高级的 gnuplot 封装,支持多种图表类型:

# 安装 (Python 依赖)
pip install fio2gnuplot

# 生成 gnuplot 脚本
fio2gnuplot -p result_bw_log -g

# 绘图
gnuplot result.pg

8.5 手动 gnuplot 绘图

# bandwidth.gnuplot
set terminal png size 1200,600
set output 'bandwidth.png'
set title 'FIO Bandwidth Over Time'
set xlabel 'Time (seconds)'
set ylabel 'Bandwidth (MB/s)'
plot 'result_bw.1.log' using ($1/1000):($2/1024/1024) with lines title 'Read BW'
gnuplot bandwidth.gnuplot

8.6 IOPS 性能分析

磁盘 IOPS 理论值

磁盘类型 转速 IOPS (理论)
SATA HDD 7200 RPM ~75-100
SAS HDD 10K RPM ~100-140
SAS HDD 15K RPM ~150-200
SATA SSD N/A 5,000-90,000
NVMe SSD N/A 100,000-1,000,000+

RAID 写惩罚

RAID 级别 读 IOPS 公式 写 IOPS 公式 写惩罚
RAID 0 N × IOPS N × IOPS 1x
RAID 1 N × IOPS (N/2) × IOPS 2x
RAID 5 N × IOPS (N/4) × IOPS 4x
RAID 6 N × IOPS (N/6) × IOPS 6x
RAID 10 N × IOPS (N/2) × IOPS 2x
其中 N = 磁盘数量, IOPS = 单盘 IOPS

示例计算: - 6 块 15K SAS 盘 (150 IOPS/盘) 做 RAID5 - 读 IOPS: 6 × 150 = 900 - 写 IOPS: 6 × 150 / 4 = 225


9. RV Script Generator 自动化工具

9.1 工具概述

RV Script Generator 是一个基于 Python/Tkinter 的图形化工具,为服务器 RV (Reliability Verification) 测试自动化生成 FIO 配置文件和 Shell 测试脚本。它集成了 IPMI 风扇控制,支持按风扇转速百分比逐级测试磁盘 I/O 性能。

技术栈: Python 3 + Tkinter (GUI) + PyInstaller (打包为 .exe)

位置: e:\Auto Test\测试脚本\FIO自动化测试脚本\RV‌ Script Generator\

9.2 使用流程 (7 步向导)

Step 1: New Project (新建项目)

- 输入项目名称 (只能包含字母、数字、下划线) - 选择输出目录 (默认为工具所在目录) - 预览: 显示将创建的完整路径

Step 2: Select Test Types (选择测试类型)

界面分为 5 个分组:

分组 包含测试
4K Random randread-4k, randwrite-4k
128K Sequential read-128k, write-128k
256K Sequential read-256k, write-256k
64K Sequential read-64k, write-64k
1M Sequential read-1M, write-1M

每个测试可单独调整: - iod (iodepth): 16 或 32 - run(s) (runtime): 120, 300, 600, 900 秒 - ramp(s) (ramp_time): 30 或 120 秒 - logms (log_avg_msec): 1000 或 12000

Custom Test Type (自定义): 可定义任意 rw/bs/tc/iodepth/runtime 组合。

FIO Settings 全局设置: - iodepth/runtime/ramp_time/log_avg_msec: 启用 "Use Global" 时覆盖所有测试的对应值 - FIO Output Case: lowercase (iops=/bw=) vs UPPERCASE (IOPS=/BW=) - 提示: Tencent 和 Yunhai 平台通常使用 UPPERCASE - Test Mode: - batch (all drives together): 所有盘在一个 FIO 命令中测试 - per-drive (one by one): 每个盘单独运行 FIO (Tencent/Steelix 常用)

Step 3: Drive Select (选择磁盘)

- 输入盘符范围,如 a-z (默认) 或 a-f - 默认覆盖 24 个盘符 (a 到 x) - 支持多字母盘符: aa-az, ba-bz, ca-cz, da-dz (共 130 个标签)

Step 4: Fan Speed (风扇转速百分比)

预设转速序列: - Standard: 20 30 40 50 60 70 75 80 85 90 95 100 (12级) - Classic: 20 30 40 50 60 70 80 90 100 (9级) - Single 100: 仅 100% - Single 20: 仅 20%

也可手动输入自定义序列 (空格分隔的百分比值)。

Step 5: Fan Control (IPMI 风扇控制平台)

10 个平台预设:

平台 控制命令 风扇数 恢复方式
Current IPT (0x3e 0x1f) raw 0x3e 0x1f $j $fan $fan 0 0xff 0xff 10 循环恢复 21%
Seaking/Machamp (0x30 0xf6) raw 0x30 0xf6 0x0$j $fan $fan 0x03 6 循环恢复 20-100
Pokemon (0x30 0xb7) raw 0x30 0xb7 0x4 0xff $fan + 0xb7 0x5 0xff $fan 1 IPMI stack restart
Marshadow (0x38 0x41) raw 0x38 0x41 0 $fan 0xff 1 恢复自动模式
Kingler (0x2e 0x11) raw 0x2e 0x11 0xa9 0x19 0x00 6 1 + 0x2e 0x11 ... 7 $fan 1 mc reset cold
Steelix (0x3e 0xf6) raw 0x3e 0xf6 $j $fan $fan 0x03 5 循环恢复 30%
Yunhai (0x3e 0x31) raw 0x3e 0x31 0x00 $fan (前导: 0x3e 0x2f 0x01) 1 恢复 50%
U90G5/Poyanghu (0x3e 0x03) raw 0x3e 0x03 0x0$j $fan 8 循环恢复 50%
Kunlun/2U42 (0x3e 0x03) raw 0x3e 0x03 $j $fan 8 循环恢复 50%
Old IPT (0x30 0xf6 plain) raw 0x30 0xf6 $j $fan $fan 0 5 循环恢复 30-100
Auto Only (no IPMI)

支持用户编辑自定义的 set_fan 和 restore 命令。

Step 6: Summary (预览)

展示所有选定参数的综合摘要,确认后进入生成步骤。

Step 7: Generate (生成)

点击生成后,在 {output_dir}/{project_name}/ 下创建:

project_name/
├── test/                    # FIO 配置文件
│   ├── randread-4k-1-16-85%-none
│   ├── read-128k-1-16-85%-none
│   └── ... (每种选定的测试类型)
├── *.sh                     # Shell 测试脚本 (每种测试类型一个)
└── result/                  # (运行后生成) 测试结果

9.3 生成的 Shell 脚本结构

每个 .sh 脚本的工作流程:

1. 初始化: 获取脚本路径、时间戳、创建结果目录
2. SMART 采集 (before): 遍历所有盘执行 smartctl --all
3. 测试循环:
   ├─ 外循环: test_case (测试类型)
   │  ├─ 外循环 (per-drive模式): $hdd 盘符
   │  │  ├─ 内循环: fan 转速
   │  │  │  ├─ IPMI 设置风扇转速 (raw 命令)
   │  │  │  ├─ sleep 等待 (5-10秒)
   │  │  │  ├─ 执行 fio {config_file}
   │  │  │  └─ 提取结果 (grep IOPS/BW → CSV)
   │  │  └─ 内循环结束
   │  └─ 外循环结束
   └─ 后处理: paste 合并各盘结果 CSV
4. SMART 采集 (after)
5. 恢复风扇到自动模式
6. 重命名结果目录 (带时间戳)

核心代码段示例 (batch 模式):

#!/bin/sh
Cur_Dir=$(cd "$(dirname "$0")";pwd)
ScriptName=$(basename "$0" .sh)
TimeStamp=$(date +%Y%m%d%H%M)_${ScriptName}
rm -rf $Cur_Dir/$ScriptName/result
mkdir -p $Cur_Dir/$ScriptName/result/smart
mkdir -p $Cur_Dir/$ScriptName/result/value
mkdir -p $Cur_Dir/$ScriptName/result/log

## Smart Log Collect
hdd='a b c d e f g h i j k l m n o p q r s t u v w x'
for i in $hdd;do
    mkdir -p $Cur_Dir/$ScriptName/result/dev/sd$i
    smartctl --all /dev/sd$i >$Cur_Dir/$ScriptName/result/smart/smart_info_sd${i}_before
done

## Set test_case
for test_case in randread-4k;do
    for fan in 20 30 40 50 60 70 75 80 85 90 95 100;do
        # IPMI 设置风扇
        ipmitool raw 0x3e 0x1f 1 $fan $fan 0 0xff 0xff
        sleep 5

        # FIO 测试
        fio $Cur_Dir/test/${test_case}-1-16-85%-none |tee $Cur_Dir/$ScriptName/result/log/${test_case}-${fan}

        # 提取结果
        cd $Cur_Dir/$ScriptName/result/log
        tc=iops
        grep -i -o "iops=[0-9]\+," ${test_case}-${fan} |tee ycy.txt
        grep -o "[0-9]\+" ycy.txt |tee $Cur_Dir/$ScriptName/result/value/$fan-${test_case}-value-$tc.csv
    done
done

## 恢复风扇
for j in `seq 1 10`;do
    ipmitool raw 0x3e 0x1f $j 21 100 0 0xff 0xff
done

## Smart Log Collect (after)
for i in $hdd;do
    smartctl --all /dev/sd$i >$Cur_Dir/$ScriptName/result/smart/smart_info_sd${i}_after
done
mv $Cur_Dir/$ScriptName/result $Cur_Dir/$TimeStamp

9.4 两种测试模式对比

Batch 模式 (all drives together)

- 所有盘在一个 FIO Job File 中配置 - 一次 fio config_file 调用测试所有盘 - 适合: 批量快速测试,Intel/Seaking 平台

循环: fan 转速
  └─ fio config_file (含 sda, sdb, sdc ... sdx 全部段)
  └─ 提取结果

Per-Drive 模式 (one by one)

- 每个盘独立 FIO 配置和运行 - 嵌套循环: 盘 → 转速 → FIO - 适合: Tencent/Steelix 平台,需要每个盘的独立结果

循环: $hdd 盘符
  └─ 循环: fan 转速
      └─ fio config_file (仅含当前 sd$i 段)
      └─ 提取结果

9.5 输出格式: UPPERCASE vs lowercase

lowercase (默认):

tc=iops
grep -i -o "iops=[0-9]\+\," ${test_case}-${fan} |tee ycy.txt
grep -o "[0-9]\+" ycy.txt |tee $Cur_Dir/$ScriptName/result/value/$fan-${test_case}-value-$tc.csv

UPPERCASE:

tc=iops
grep -o "IOPS=[0-9]\+," ${test_case}-${fan} |tee ycy.txt
grep -o "[0-9]\+" ycy.txt |tee $Cur_Dir/$ScriptName/result/value/$fan-${test_case}-value-$tc.csv
区别: FIO 的不同版本的输出格式可能不同,UPPERCASE 匹配 IOPS= 模式,lowercase 匹配 iops= 模式。Tencent 和 Yunhai 平台通常使用 UPPERCASE。

9.6 结果提取逻辑

IOPS 提取 (tc=iops)

FIO Output: "... iops=134567, ..."
    → grep "iops=[0-9]+" → ycy.txt
    → grep numbers → value/{fan}-{test_case}-value-iops.csv

BW 提取 (tc=bw)

FIO Output: "... bw=528MiB/s ..."
    → grep "bw=[0-9]+KiB" → ycy
    → 单位转换 (KiB→MiB: ÷1024) → value/{fan}-{test_case}-value-bw.csv

lowercase 模式下 KiB/KB 自动除以 1024 转换为 MiB; 如果已经是 MiB 则直接输出。

9.7 后处理

# 合并所有风扇转速的结果
cd $Cur_Dir/$ScriptName/result/value
paste -d ',' `ls |grep ${test_case}-value-$tc.csv|xargs` \
    |tee $Cur_Dir/$ScriptName/result/${test_case}-value-$tc.csv

# 合并所有盘的结果
cd $Cur_Dir/$ScriptName/result/dev/sd$i
fio_iops_file=`ls |grep sd$i |grep $test_case|grep $tc`
awk -F ',' '{print $1","$2}' $fio_iops_file \
    |tee $Cur_Dir/$ScriptName/result/${test_case}/sd${i}_${test_case}

# 最终合并
cd $Cur_Dir/$ScriptName/result/${test_case}
paste -d ',' `ls |grep "$test_case"|grep sd|xargs` \
    |tee $Cur_Dir/$ScriptName/result/${test_case}-log-$tc.csv

最终生成的 CSV: - 行: 日志采样时间点 - 列: 各盘的 IOPS/BW 值


10. 使用示例

10.1 单盘随机读测试 (命令行)

fio --name=randread-test \
    --filename=/dev/sda \
    --rw=randread \
    --bs=4k \
    --ioengine=libaio \
    --direct=1 \
    --iodepth=16 \
    --numjobs=1 \
    --runtime=120 \
    --ramp_time=30 \
    --time_based

10.2 多盘并发测试 (Job File)

创建 multi_disk.fio:

[global]
ioengine=libaio
direct=1
rw=randread
bs=4k
iodepth=16
runtime=120
ramp_time=30
time_based

[sda]
filename=/dev/sda
size=85%

[sdb]
filename=/dev/sdb
size=85%

[sdc]
filename=/dev/sdc
size=85%

运行:

fio multi_disk.fio

10.3 全盘顺序写测试

fio --name=seq-write \
    --filename=/dev/sda \
    --rw=write \
    --bs=128k \
    --ioengine=libaio \
    --direct=1 \
    --iodepth=16 \
    --numjobs=1 \
    --size=100%
警告: --rw=write 会覆盖磁盘数据!确保测试盘无重要数据。

10.4 混合读写测试

fio --name=mixed-rw \
    --filename=/dev/sda \
    --rw=randrw \
    --rwmixread=70 \
    --bs=4k \
    --ioengine=libaio \
    --direct=1 \
    --iodepth=16 \
    --runtime=300 \
    --time_based

10.5 延迟测试

使用不同的 iodepth 观察延迟变化:

# 低队列深度 (低延迟场景)
fio --name=lat-qd1 --filename=/dev/sda --rw=randread --bs=4k \
    --ioengine=libaio --direct=1 --iodepth=1 --runtime=60 --time_based

# 高队列深度 (高并发场景)
fio --name=lat-qd32 --filename=/dev/sda --rw=randread --bs=4k \
    --ioengine=libaio --direct=1 --iodepth=32 --runtime=60 --time_based

关键对比指标: clat avg, clat p99, clat p99.9

10.6 数据完整性校验

fio --name=verify-test \
    --filename=/dev/sda \
    --rw=randwrite \
    --bs=4k \
    --size=1G \
    --ioengine=libaio \
    --direct=1 \
    --verify=md5 \
    --verify_fatal=1

# 验证阶段 (重新读取并校验)
fio --name=verify-test \
    --filename=/dev/sda \
    --rw=randread \
    --bs=4k \
    --size=1G \
    --ioengine=libaio \
    --direct=1 \
    --verify=md5 \
    --verify_only

10.7 日志记录与绘图完整流程

# 1. 准备结果目录
PROJECT_DIR="/root/rv_test"
mkdir -p $PROJECT_DIR/result

# 2. 运行 FIO 并记录日志
fio --name=test \
    --filename=/dev/sda \
    --rw=randread \
    --bs=4k \
    --ioengine=libaio \
    --direct=1 \
    --iodepth=16 \
    --runtime=300 \
    --ramp_time=30 \
    --time_based \
    --write_bw_log=$PROJECT_DIR/result/sda_bw \
    --write_iops_log=$PROJECT_DIR/result/sda_iops \
    --write_lat_log=$PROJECT_DIR/result/sda_lat \
    --log_avg_msec=1000 \
    --output=$PROJECT_DIR/result/fio_output.txt

# 3. 使用 fio_generate_plots 绘图
fio_generate_plots sda $PROJECT_DIR/result/charts

# 4. 查看图表
ls $PROJECT_DIR/result/charts/
# sda_bw.svg, sda_iops.svg, sda_clat.svg, sda_slat.svg, sda_lat.svg

10.8 服务器批量测试 (RV Script Generator 工作流)

1. 打开 RV Script Generator.py (或 .exe)
2. New Project → 输入 "rv_myproject"
3. Select Test Types → 勾选全部 10 种预设
4. Drive Select → 输入 "a-x"
5. Fan Speed → 选择 "Standard" (12级)
6. Fan Control → 选择 "Current IPT (0x3e 0x1f)"
7. Summary → 确认参数无误
8. Generate → 生成脚本和配置文件

输出:
  rv_myproject/
  ├── test/             (10 个 FIO 配置文件)
  ├── randread-4k.sh    (每种测试 1 个 .sh)
  ├── randwrite-4k.sh
  ├── ...
  └── write-1M.sh

运行:
  cd rv_myproject
  chmod +x *.sh
  ./randread-4k.sh
  ./randwrite-4k.sh
  ...

11. 高级用法

11.1 IO 引擎深度对比

场景 推荐引擎 原因
本地磁盘/SDD libaio 异步 IO, 支持高队列深度
简单测试 sync 无需额外依赖
文件系统测试 mmap 模拟内存映射行为
网络存储 net RAW socket IO
Ceph RBD rbd 直接访问 RADOS 块
SCSI 设备 sg SCSI 通用接口

11.2 NUMA 绑定

多路服务器上绑定 NUMA 节点以提高测试稳定性:

fio --name=numa-test \
    --filename=/dev/nvme0n1 \
    --rw=randread --bs=4k \
    --ioengine=libaio --direct=1 \
    --iodepth=32 --numjobs=4 \
    --cpus_allowed=0-7 \
    --cpus_allowed_policy=split \
    --numa_cpu_nodes=0 \
    --numa_mem_policy=local \
    --runtime=300 --time_based

11.3 多客户端模式 (Client/Server)

多台机器协同测试:

# Server 端 (每台被测机器)
fio --server --daemonize=/tmp/fio.pid

# Client 端 (控制机)
fio --client=10.0.0.1 --client=10.0.0.2 job.fio

11.4 IO 日志回放

捕获和重放真实 IO 工作负载:

# 记录 IO trace
fio --name=record \
    --filename=/dev/sda \
    --rw=randread --bs=4k \
    --write_iolog=/tmp/replay.log \
    --runtime=300 --time_based

# 重放 IO trace
fio --name=replay \
    --filename=/dev/sdb \
    --read_iolog=/tmp/replay.log

11.5 硬盘预处理 (Pre-conditioning)

SSD 测试前进行全盘顺序写确保稳态:

# 第一次全盘写 (预处理)
fio --name=precondition \
    --filename=/dev/sda \
    --rw=write --bs=128k \
    --ioengine=libaio --direct=1 \
    --iodepth=16 --numjobs=1 \
    --size=100%

# 第二次全盘写 (确认稳态)
fio --name=precondition2 \
    --filename=/dev/sda \
    --rw=write --bs=128k \
    --ioengine=libaio --direct=1 \
    --iodepth=16 --numjobs=1 \
    --size=100%

# 正式测试
fio --name=steady-test \
    --filename=/dev/sda \
    --rw=randwrite --bs=4k \
    --ioengine=libaio --direct=1 \
    --iodepth=16 --runtime=1800 --time_based

11.6 随机分布算法

--random_distribution=zipf:1.2    # Zipf 分布 (热点数据)
--random_distribution=pareto:0.9  # Pareto 分布 (80/20)
--random_distribution=random      # 均匀随机 (默认)

12. 故障排查

12.1 libaio 缺失

症状: 编译时报 fio: engine libaio not loadable

# CentOS/RHEL
yum install libaio-devel -y

# 已编译安装的需重新编译
cd fio-3.7
make clean
./configure && make && make install

12.2 设备重叠

症状: fio: job 'xxx' dropped because of overlapping

原因: 多个 Job 指定了相同的 filename

解决: 确保每个 Job 的 filename 唯一,或使用不同的起始 offset:

[sda_part1]
filename=/dev/sda
offset=0
size=50G

[sda_part2]
filename=/dev/sda
offset=50G
size=50G

12.3 权限问题

症状: fio: looks like your file doesn't exist, or you don't have permission

解决: 以 root 运行或确保对设备文件有读写权限:

# 检查权限
ls -la /dev/sda

# 以 root 运行
sudo fio ...

# 或调整用户组
sudo usermod -a -G disk $USER

12.4 日志路径不存在

症状: 日志目录无法写入

解决: 确保日志路径中的目录已创建:

mkdir -p /root/rv_test/result/dev/sda

12.5 大容量设备 size 计算

size=85% 表示使用设备 85% 的容量。对于大容量设备 (如 16TB),测试时间会非常长。

建议: - 随机测试: 使用 runtime=300 + time_based 代替 size - 顺序测试: 指定具体大小 size=500G 或使用 runtime

12.6 GFIO 启动失败

症状: gfio: error while loading shared libraries: libgtk-x11-2.0.so

# CentOS/RHEL
yum install gtk2 gtk2-devel -y

# 检查库路径
ldconfig -p | grep gtk

# 如仍失败,设置 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/lib64:$LD_LIBRARY_PATH
gfio

12.7 编译错误: zlib

症状: configure: error: zlib not found

yum install zlib-devel -y    # CentOS/RHEL
apt-get install zlib1g-dev   # Debian/Ubuntu

13. 相关文档

- FIO 官方文档 - FIO GitHub 仓库


14. 版本历史

版本 日期 变更说明
v1.0 2026-05-27 初始版本, 基于 CSDN pansaky 博客 + RV Script Generator 源码整理

参考来源: CSDN pansaky 博客 (https://blog.csdn.net/pansaky/article/details/83689110), FIO 官方文档, RV Script Generator v1.0 源码