硬盘性能测试笔记学习全套 -- Fio

发布时间 2023-11-13 02:18:49作者: 梭梭666

Top

FIO 下载地址

Github Download -- FIO

Kernel Download -- FIO

FIO 安装

./configure --enable-gfio # 只有加这个参数才能编译安装gfio
make fio
make gfio
make install

参数解析

--readwrite=${RW}   # 表示测试类型; 分顺序读  -rw=read ,随机读 -rw=randread,顺序写 -rw=write,随机写-rw=randwrite ,混合随机读写模式  -rw=randrw
--bs=4k            # 表示 I/O block大小,默认是4k; 也可指定为 --blocksize=4k
--runtime=300s     # 指定在多少秒后停止进程。如果未指定该参数,fio将执行至指定的文件读写完全完成
--numjobs=16       # 指定job的克隆数(线程)
--iodepth=64 ${PARA_LINE}  # 表示 I/O 队列深度; 如果ioengine采用异步方式,该参数表示一批提交保持的io单元数
--filename=/dev/${DEV_LIST}  # 表示要测试的裸设备(硬盘或分区); 切勿在系统分区做测试,会破坏系统分区,而导致系统崩溃。若一定要测试系统分区较为安全的方法是:在根目录下创建一个空目录,在测试命令中使用directory参数指定该目录,而不使用filename参数
--name=${DEV_LIST}_${RW}_4k_16_64  # 定义测试任务名称。


-end_fsync=0 
--group_reporting  # 定义测试结果显示模式,group_reporting 表示汇总每个进程的统计信息,而非以不同 job汇总展示信息
-direct=1,   # 定义是否使用direct IO,可选值如下:值为0,表示使用buffered IO;值为1,表示使用 direct IO; 测试过程绕过机器自带的buffer。使测试结果更真实;
-ioengine=${IO_ENGINE} # 指定I/O 处理处理模型, libaio指的是异步模式,如果是同步就要用sync, 同步IO一次只能发出一个IO请求, 
-thread  # 指定创建线程的方式,将使用pthread_create来创建线程;另一种是fork创建进程。进程的开销比线程要大,一般都采用thread测试
-time_based  # file若已被完全读写或写完,强制执行完runtime规定的时间。它是通过循环执行相同的负载来实现的,与runtime相对应
-buffer_compress_percentage=0  # 设定缓冲区数据的压缩级别
-invalidate=1 
-norandommap 
-randrepeat=0  # 对于随机IO负载,配置生成器的种子,使得路径是可以预估的,使得每次重复执行生成的序列是一样的, 不设置的话, 会影响seqwrite,randwrite,randread, 
-exitall 
-size=${FILE_SIZE}  # 定义测试IO操作的数据量,若未指定runtime这类参数,fio会将指定大小的数据量全部 读/写完成,然后才停止测试。该参数的值,可以是带单位的数字,比如size=10G,表示读/写的数据量为10GB;也可是百分数,比如size=20%,表示读/写的数据量占该设备总文件的20%的空间。建议测试数据量为内存两倍大,尽量避免缓存影响
--offset_increment=100G # 表示跳过指定的数据量大小,

--loop   # 定义硬盘执行的圈数, loops与runtime是两个不能同时存在的两个参数
-ramp_time # 设定在记录任何性能信息之前要运行特定负载的时间。这个用来等性能稳定后,再记录日志结果,因此可以减少生成稳定的结果需要的运行时间
--output=txt,pdf,html  # 输出的文件名
--output-format:# 定义日志输出格式(normal',terse', json', orjson+')
--rwmixwrite  # 在混合读写模式下, 写所占用的百分比 
--rwmixread    # 在混合读写模式下, 读所占用的百分比 
-lockmem    # 表示锁定内存的大小
--hugepage-size=int  # 设置大页数量 
zero_buffers   #  用0初始化系统buffer。
nrfiles=8      #  每个进程生成文件的数量。
nrfiles=8   # 每个进程生成文件的数量
-cpus_allowed=0,5,8-15  # 绑核 
-cpus_allowed_policy=split # 设置fio分配cpu的策略
	# shared  # 所有作业将共享指定的CPU集
	# split   # 每个作业将从CPU集中获得一个唯一的CPU
-numa_cpu_nodes=0  # 设置此作业在指定NUMA节点的cpu上运行, 参数允许使用逗号分隔的cpu编号列表, '0-3' or 'all', 可用策略为:`default', `prefer', `bind', `interleave' or `local'
-uid='int'  # 用户 ID 
-gid='int'  # 组 ID 
--rate_iops=500  # 锁定IOPS
--rate=100m      # 锁定带宽

################################  测试报告
--write_bw_log=str  # <--name参数值>_bw.<线程ID>.log, 同一个 Fio , 针对每个 线程都会生成一个文件 
--write_lat_log=str  # <--name参数值>_lat.<线程ID>.log, 同一个 Fio , 针对每个 线程都会生成一个文件
--write_iops_log=str  #  <--name参数值>_iops.<线程ID>.log, 同一个 Fio , 针对每个 线程都会生成一个文件
--bsrange=512-2048  # 提定数据块的大小范围   
--bssplit=4k/50:8k/20:16k/10:32k/20  # 对块大小进行更细粒度的控制,顺序不重要。如果百分比为空,fio将均匀地填充剩余的值,比如:4k/50:1k/:32k/ ; 
	若您希望工作负载具有50%的2k读取和50%的4k读取,同时具有90%的4k写入和10%的8k写, 
		比如: bssplit=2k/50:4k/50,4k/90:8k/10
--blocksize_range  # 指定了block size的范围,相当于动态的block size
-directory=   # 文件创建的目录,当对NFS文件系统进行测试时,该参数可以指定客户端NFS挂载的目录


# 对 BW 影响显著的参数 
--bs=4k 
--numjobs=2  
--iodepth=32 
-direct=1      
--offset_increment=100G
-ioengine=libaio | psync  
-thread

当 SSD 的 scheduler 为 mq-deadline 时, randread 的 IOPS  会高些
当 SSD 的 scheduler 为 none 时, randwrite 的 IOPS  会高些

点我回顶部

结果分析

BW:  基于样本的带宽统计
IOPS : # IOPS 
lat    # I / O完成延迟的分布; (nsec/usec/msec)
clat   # 完成延迟。 与板条同名,表示从提交到完成I / O件的时间。 对于同步I / O,clat通常等于(或非常接近)0;
slat   # 提交延迟(min为最小值,max为最大值,avg为平均值,stdev为标准偏差)。 这是提交I / O所花费的时间
cpu    # 	CPU使用率
IO depths  # I / O深度在整个工作周期中的分布
util   # 磁盘利用率。 值为100%表示我们使磁盘一直处于繁忙状态,而50%的磁盘将有一半的时间处于空闲状态

自带图形化工具

# 按照依赖包 
yum install -y gnuplot

fio_generate_plots 接受的唯一参数就是这个日志文件名的prefix

单位换算

Mbit/s的意思是每秒中传输10^6 bit的数据,也写成Mbps
MB/s的意思是每秒中传输10^6 byte的数据
MiB/s的意思是每秒中传输2^20 byte的数据,不太常用
PS:所以如果一个运营商声称自己的传输带宽是1 Mbps
MB/s=MiB/s *1.024
Mbit/s * 8 = MB/s
Mbit/s = MiB/s * 0.1192
GB=0.9313225746GiB

相关命令

# SATA, SAS 盘安全擦除 
hdparm --user-master u --security-set-pass  PASSWD  /dev/sdx  # 获取权限 
hdparm --user-master u --security-erase PASSWD /dev/sdx       # 执行安全擦除  



##### HDD
1. 关闭缓存 
sdparm -s WCE=0 --save /dev/sd$i : 关闭SAS HDD 缓存
hdparm -W 0 /dev/sd$i            : 关闭 SATA HDD 缓存
2. 修改算法
for i in {a..l};do echo mq-deadline > /sys/block/sd$i/queue/scheduler;done
3. 收集所有盘信息 
4. 修改脚本,注意一下几点 : 
threads = 2 
iodepth  : 32  
--offset_increment=100G
5. 测试
nohup &>/dev/null bash run_parallel_hdd.sh &


## 获取 缓存信息 
sdparm -g WCE  /dev/sda  #  获取 SAS HDD 缓存
hdparm -W 0 /dev/sd$i    #  获取 SATA HDD 缓存

# 查看盘列表信息 
lsscsi -g -s  -k
lsblk -p
nvme list 

点我回顶部

结果格式化

awk '/IOPS/{split($2, iops_len, "=");split($4, bw_li, ")");split(bw_li[1], bw_li_li, "(");printf("%s,--- %s\n", bw_li_li[2], iops_len[2]); }' hdd_sda_read.log

awk '/IOPS/{
split($2, iops_li, "=")
split($4, bw_li, ")")
gsub(",", "", iops_li[2])
bw=substr(bw_li[1], 2)
printf("%s   %s\n", iops_li[2], bw)
}' hdd_sda_read.log

# 获取 IOPS 和 BW 
awk '/IOPS/{split($2, iops_li, "=");split($4, bw_li, ")");gsub(",", "", iops_li[2]);bw=substr(bw_li[1], 2);printf("%-10s   %-10s\n", iops_li[2], bw);}' hdd_sda_read.log



# 获取 IOPS 和 BW , 并自动处理 带宽的单位,统一换算为 MB/s 
awk '/IOPS=/{split($2, iops_li, "=");split($4, bw_li, ")");gsub(",", "", iops_li[2]);bw=substr(bw_li[1], 2);end=match(bw, "kB/s|MB/s|GB/s", bws);bw_num=substr(bw, 1, end - 1);if (bws[0] == "kB/s"){bw_num/=1000;};if (bws[0] == "GB/s"){bw_num*=1000;};printf("%-10s   %-10s\n", iops_li[2], bw_num"MB/s");}' hdd_sdm_randread.log


# 获取 设备名, Block , Threads, IoDepth 大小
cat hdd_sda_read.log | grep  pid=  | awk '{print $1}' | sed 's/.$//g' | awk 'BEGIN{FS="_"}{printf("%-9s %-5s %-5s %-5s\n",$1,$2,$3,$4); }'

# 格式化 获取 设备名, Block , Threads, IoDepth  
awk '/pid=/{ff=$1;gsub(":","",ff);split(ff,li,"_");printf("%-10s  %-10s  %-6s  %-6s  %-6s\n", li[1],li[2],li[3],li[4],li[5]);'} hdd_sda_read.log



# find 遍历目录下文件,但不打印当前目录文件本身
for fff in `find ./hdd_fio_log_TOSHIBA_HDD_SATA_8T/*`; do echo  $fff ; done

# find 遍历目录下文件,但不打印当前目录文件本身,然后格式化输出每个FIO 的 IOPS 和 BW 数据
for fff in `find ./hdd_fio_log_TOSHIBA_HDD_SATA_8T/*`; do printf "%s\n" ${fff}; awk '/IOPS=/{split($2, iops_li, "=");split($4, bw_li, ")");gsub(",", "", iops_li[2]);bw=substr(bw_li[1], 2);end=match(bw, "kB/s|MB/s|GB/s", bws);bw_num=substr(bw, 1, end - 1);if (bws[0] == "kB/s"){bw_num/=1000;};if (bws[0] == "GB/s"){bw_num*=1000;};printf("%-10s   %-10s\n", iops_li[2], bw_num"MB/s");}' $fff ; done

# 过滤出有 IOPS 和时延数据的行,然后将其每个FIO 的数据合并为 一行 
awk '/IOPS=|clat.*avg=/{if($0 ~ "IOPS=")ORS="";else ORS="\n"; print $0;}' hdd_sda_read.log


# 格式化输出一个文件中所有FIO程序的的 IOPS, BW , 时延数据,也可根据需要稍微修改脚本,使其所有数据输出在一行,其中每 3 个数据为一组(IOPS , BW, CLAT),且 BW 的单位默认为 MB/s,  CLAT 的单位为 msec(毫秒)
awk '/IOPS=|clat.*avg=/{
if($0 ~ "IOPS="){
ORS=""
split($2, iops_li, "=")
split($4, bw_li, ")")
gsub(",", "", iops_li[2])
bw=substr(bw_li[1], 2)
end=match(bw, "kB/s|MB/s|GB/s", bws)
bw_num=substr(bw, 1, end - 1)
if (bws[0] == "kB/s"){bw_num/=1000;}
if (bws[0] == "GB/s"){bw_num*=1000;}
printf("%-10s   %-10s  ", iops_li[2], bw_num"MB/s")}
else {
ORS="\n"
cunit=substr($2,2,4)
sub(",","",$5)
sub("avg=","",$5)
if (cunit == "usec"){$5/=1000}
printf("%-10s",$5)}
}' hdd_sda_read.log
	# 结果输出格式如下: 
	==========================================
	16.8k        68.0MB/s    3.79792
    3734         245MB/s     17.14
    946          248MB/s     67.62
    253          266MB/s     126.23
    242          254MB/s     263.88

# V2 格式化输出一个文件中所有FIO程序的的 IOPS, BW , 时延数据,也可根据需要稍微修改脚本,使其所有数据输出在一行,其中每 3 个数据为一组(IOPS , BW, CLAT),且 BW 的单位默认为 MB/s,  CLAT 的单位为 msec(毫秒)
awk '/IOPS=|clat.*avg=/{
if($0 ~ "IOPS="){
ORS=""
split($2, iops_li, "=")
split($4, bw_li, ")")
gsub(",", "", iops_li[2])
if(iops_li[2]~/k/){iops_li[2]*=1000}
bw=substr(bw_li[1], 2)
end=match(bw, "kB/s|MB/s|GB/s", bws)
bw_num=substr(bw, 1, end - 1)
if (bws[0] == "kB/s"){bw_num/=1000;}
if (bws[0] == "GB/s"){bw_num*=1000;}
printf("%-10s   %-10s %4s   ", iops_li[2], bw_num, "MB/s")}
else {
ORS="\n"
cunit=substr($2,2,4)
sub(",","",$5)
sub("avg=","",$5)
if (cunit == "msec"){$5*=1000}
if (cunit == "nsec"){$5/=1000}
printf("%-10s %4s\n",$5, "usec")}
}' $1
	# 结果输出格式如下: 
    ==========================================
    205k         841        MB/s   37.2867    usec
    82.0k        336        MB/s   10.816     usec
    103k         843        MB/s   75.9789    usec
    206k         842        MB/s   154.23     usec
    207k         847        MB/s   4952.51    usec
    206k         843        MB/s   620.07     usec
    206k         846        MB/s   1238.31    usec
    206k         845        MB/s   9926.19    usec
    207k         846        MB/s   1237.85    usec

# 对 Fio 文件中测试文件(即测试设备文件)的提取 
awk -F':' '/util=/{print $1}' hdd_sdd_randread.log   | xargs


# 对 Fio 文件中测试模式的提取 
cat hdd_sdd_randwrite.log   | grep rw= | sed  '/rw=/s/.*rw=\(.*\), bs=.*/\1/g'
sed '/rw=/s/.*rw=\(.*\), bs=.*/\1/gp' -n ssd_nvme2n1_randread.log
awk -F'rw=' '/rw=/{split($2,li,",");print li[1];}' hdd_sdd_randread.log | xargs

# 对 Fio 文件中测试 ioengine 的提取 
awk -F'ioengine=' '/rw=/{split($2,li,",");print li[1];}' hdd_sdd_randread.log | xargs

# 对 Fio 文件中测试 iodepth 的提取
awk -F'iodepth=' '/rw=/{split($2,li,",");print li[1];}' hdd_sdd_randread.log
awk -F'iodepth=' '/rw=/{printf("%s ",$2)}' hdd_sdd_randread.log | xargs

# 对 Fio 文件中测试 线程数的 提取 
awk -F'jobs=' '/jobs=/{split($2, li, ")");printf("%s ",li[1])}' hdd_sdd_randread.log | xargs

# 对 Fio 文件中测试块大小的提取, 默认单位为 KiB
awk -F'bs=' '/rw=/{split($2,li,"-");split(li[1],li02," ");if(li02[2] ~ "KiB"){gsub("KiB","",li02[2]);printf("%s ",int(li02[2]));}else{gsub("B","",li02[2]);bs=li02[2]/=1024;printf("%s ",bs);}}' hdd_sdd_randread.log | xargs

# 获取 Bios 版本
dmidecode  -t bios | grep 'Version:' | sed '1p' -n  | awk '{print $2}' | xargs

# 获取 CPU 型号
lscpu | awk '/^Model name:/{i=3;while (i<=NF) {print $i; i++} }' | xargs

# 获取 CPU 数量
lscpu | awk '/^Socket/{print $2}' | xargs

# 获取 盘的  FW  
smartctl -i /dev/sda | awk '/^Firmware Version/{print $NF}' | xargs

# 获取 盘 的 序列号
smartctl -i /dev/sda | awk '/^Serial Number/{i=3;while (i<=NF) {print $i; i++}}' | xargs
	# 第二种方法
	lsblk -d -o 'SERIAL' /dev/sda | sed '$p' -n | xargs
	
# 获取 盘 的 转动率
smartctl -i /dev/sda | awk '/^Rotation Rate/{i=3;while (i<=NF) {print $i; i++}}' | xargs

# 获取 盘 的用户容量
smartctl -i /dev/sdb | awk '/^User Capacity|^Total NVM Capacity/{i=$(NF-1)$NF;gsub("\\[|\\]","",i);print i}' | xargs

# 获取 盘 的 Model 号  
smartctl -i /dev/sda | awk '/^Device Model|^Device Model/{i=3;while (i<=NF) {print $i; i++}}' | xargs
	# 第二种方法
	lsblk -d -o 'MODEL' /dev/sda | sed '$p' -n | xargs
# 获取 盘 的 厂商名称 Vendor
smartctl -i /dev/sda | awk '/^Device Model|^Model Number|^Vendor/{if($0 ~ /Model/){print $3}else{print $2;}}' | xargs

# 获取盘 的 I/O 调度算法
cat /sys/block/sda/queue/scheduler | sed -e 's#.*\(\[.*\]\).*#\1#g' -e 's/^.//g' -e 's/.$//g'
	# 第二种方法
	lsblk -d -o 'SCHED' /dev/sda | sed '$p' -n | xargs


# 获取 NVME 盘信息 
lspci  | grep -i non-v  | awk '{print $1}' | xargs -i lspci  -vvv -s {} > nvme_AIC_lspci_info.log

# 获取 阵列卡数量
storcli64 show | sed '/Ctl Model/,/Ctl=Controller/p' -n | sed -e '1,2d' -e '$d' -e '/^$/d' | sed '$d'
# 获取 阵列卡 控制 ID  
storcli64 show | sed '/Ctl Model/,/Ctl=Controller/p' -n | sed -e '1,2d' -e '$d' -e '/^$/d' | sed '$d' | head -1  | awk '{print $1}'
# 根据 阵列卡控制 ID 获取 机架 ID  
storcli64 /c0 show | sed '/EID:Slt/,$p' -n  | sed '3p' -n  | awk -F':' '{print $1}'
#  获取阵列卡下的所有盘 
storcli64 /c0/e251/sall show | sed '/EID:Slt/,$p' -n | sed '/^-.*-$/,/^-.*-$/p' -n | sed -e '1d' -e '$d'

lspci | egrep -i 'raid.*broadcom|contro.*broadcom|contro.*storage'
# PMC
smartpqi
aacraid
# LSI 
mpt3sas
megaraid_sas


# PMC 卡语句 
# 获取卡列表 
arcconf list | sed '/Controller ID/,$p' -n | sed -e '/^$/d' -e '1,2d' -e '$d' | grep 'Controller'
# 获取卡 ID  
arcconf list | sed '/Controller ID/,$p' -n | sed -e '/^$/d' -e '1,2d' -e '$d' | grep 'Controller' | awk '{print $2}' | cut -d':' -f1 | xargs 

# 根据 nvme 盘符名获取 BUS 号  
readlink -f /sys/block/nvme0n1 |cut -d '/' -f 6
# 做性能分析或调优,测试过程中需要收集 iostat 信息
iostat -xdm 1 3 > shi


# linux shell readlink 获取当前脚本文件绝对路径
https://blog.csdn.net/whatday/article/details/105184908

# 解决硬盘乱序的问题 
lsscsi -i | awk '{ii=1;while(ii<=NF){if(ii==(NF-1)){ii++;continue;};printf("%-20s",$ii); ii++; };print ""}'

lsblk -d -o 'HCTL,MODEL,SERIAL,SIZE,TYPE,VENDOR,MIN-IO'
lsblk -d -o 'HCTL,MODEL,SERIAL,SIZE,TYPE,VENDOR,MIN-IO,STATE'
lsblk -d -o 'HCTL,MODEL,SERIAL,SIZE,TYPE,VENDOR,MIN-IO,STATE' | sed -e '1d;/disk/p' -n | sort -t ':' -k 3 -n


lsscsi -i | awk '{ii=1;while(ii<=NF){if($ii ~ "^/dev/"){ii++;continue;};printf("%-20s",$ii); ii++; };print ""}'
# 取消 NVME 
lsscsi -i -N | awk '{ii=1;while(ii<=NF){if($ii ~ "^/dev/"){ii++;continue;};printf("%-20s",$ii); ii++; };print ""}'


cat dmesg_after | egrep 'scsi.*Direct-Access*'

# 检索 dmesg 日志中的 scsi 设备 
cat err_env_2023.06.07.20.44.46/dmesg_after | egrep 'scsi.*Direct-Access*' | awk '{ii=6;while(ii<=NF){printf("%-s",$ii);ii++;}print ""}'  > ff4

# 排除 硬盘信息, 排序并格式化
lsblk -d -l -n -o 'HCTL,MODEL,SERIAL,SIZE,TYPE,VENDOR,MIN-IO,STATE' | sed -e 's/INTEL //g' -e 's/^[0-9]*://gp' -n | sort -t ':' -k 2 -n | awk '{ii=1;while(ii<=NF){if(ii ~ /2|3/){printf("%-25s",$ii)}else{printf("%-12s",$ii);};ii++};print " "}'

lsblk -d -l -n -o 'HCTL,MODEL,SERIAL,SIZE,TYPE,VENDOR,MIN-IO,STATE' | sed -e 's/INTEL //g' -e 's/^[0-9]*://gp' -n | sort -t ':' -k 2 -n | xargs -n 8


# 获取各个逻辑盘所对应的 V ID 
storcli64 /c0/vall show | sed '/^DG\/VD/,/^VD=Virtual/p' -n | sed -e '/^$/d' -e '/Optl/p' -n | awk '{print $1}' | cut -d'/' -f2 | xargs






# 网卡
lspci -vvv -s 18:00.0 2> /dev/zero | egrep -i '[[:space:]]LnkCap:|[[:space:]]LnkSta:' | awk -F: '{print $2}' | sed 's/\t//gp' -n | awk -F',' '{ii=1;while(ii<=NF){if($ii ~ "Speed|Width")printf("%-16s",$ii);ii++}print " ";}'

lspci -vvv -s 18:00.0 2> /dev/zero | egrep -i '[[:space:]]LnkCap:|[[:space:]]LnkSta:' | awk -F: '{print $2}' | sed 's/[[:space:]]*//gp' -n | awk -F',' '{ii=1;while(ii<=NF){if($ii ~ "Speed|Width")printf("%-16s",$ii);ii++}print " ";}'

lshw -C network | awk 'BEGIN{RS="*-network[:0-9]*"; FS="\n"}{if ($0 ~ "logical name.*ens2np0\n"){printf $0"\n";}}'

cat lshw_info  | awk 'BEGIN{RS="*-network[:0-9]*"; FS="\n"}{if ($0 ~ "logical name.*ens2np0\n"){printf $0"\n";}}' | egrep 'description|product|vendor|bus info|logical name|serial|width|capacity' | sed 's#^\s*##gp' -n

cat lshw_info  | awk 'BEGIN{RS="*-network[:0-9]*"; FS="\n"}{if ($0 ~ "logical name.*ens2np0\n"){printf $0"\n";}}' | awk -F':' '/configuration/{print $2}' | awk '{ii=1;while(ii<=NF){print $ii;ii++}}' | egrep 'autone|driver|version|duplex|firm|link|port|multi'

cat lshw_info  | awk -v ddd="ens2np0" 'BEGIN{RS="*-network[:0-9]*"; FS="\n"}{if ($0 ~ "logical name.*"ddd"\n"){printf $0"\n";}}' | awk -F':' '/configuration/{print $2}' | awk '{ii=1;while(ii<=NF){print $ii;ii++}}' | egrep 'autone|driver|version|duplex|firm|link|port|multi'


点我回顶部

SCSI 子系统讲解

lsscsi 
-s 显示容量大小。
-c 用全称显示默认的信息。
-d 显示设备主,次设备号。
-g 显示对应的sg设备名。
-H 显示主机控制器列表,-Hl,-Hlv。
-l 显示相关属性,-ll,-lll=-L。
-v 显示设备属性所在目录。
-x 以16进制显示lun号。
-p 输出DIF,DIX 保护类型。
-P 输出有效的保护模式信息。
-i 显示udev相关的属性-w 显示WWN
-t 显示相应传输信息(ATA,FC,SBP,ISCSI,SPI,SAS,SATA,USB),-Ht,-tl.(包括sas地址)<br><br>
列出SCSI设备(或主机)及它们的属性
第一列:SCSI设备id:host, channel,id,lun。
第二列:设备类型。
第3,4,5列:设备厂商,型号,版本信息。
最后一列:设备主节点名

从编号可以看出,第一级是host,第二级是channel,第三级是target编号,第四级是LUN号
h == hostadapter id (first one being 0)
c == SCSI channel on hostadapter (first one being 0)
t == ID
l == LUN (first one being 0)
	一个主板可能接多个host,比如上面的服务器,在有多个sas芯片的情况下,肯定就有多个host。一个sas芯片又可以分割为多个通道,也就是channel,也叫bus。一个通道下多个target,一个target下多个lun。
如果一个硬盘支持双通道,那么在scsi层,就是展示为两个scsi标号。
	注意channel编号和id编号是底层驱动自行管理的,而host编号(也就是前k)则是linux scsi子系统自行管理(参看static DEFINE_IDA(host_index_ida)(drivers/scsi/host.c))
	引入target概念后,每个device内部可以看成被分为被多个target,每个target下面接着多个lun
	lun是能够接收scsi命令的主体
	
	
# 执行以下命令扫描总SCSI线
echo "- - -" > /sys/class/scsi_host/host5/scan
	hostX中"X"是是主机的序号, 如果/sys/class/scsi_host目录下有多个的话, 需要对每一目录都执行该操作
	“- - -” 是通配符, 告诉SCSI总线需扫描所有的控制器、通道和;UN
# 重新扫描特定设备
echo “1” > /sys/class/block/sdX/device/rescan
    sdX "X"是需要重新扫描的设备
    “1” 是标志使SCSI重新扫描该设备,更新该设备的信息
# 移除现有的硬盘
echo "scsi remove-single-device 0 0 10 0 " > /proc/scsi/scsi
# 添加现有的 scsi 设备, 若不存在则无法生效
echo "scsi add-single-device 0 0 10 0 " > /proc/scsi/scsi
# scsi_id命令:查询scsi设备id号;
scsi_id –g –u –s /dev/sda
# HBA WWWN:
cat /sys/class/fc_host/host*/node_name
# DISK wwwn:
ls -l /dev/disk/by_id|grep -v part
# 手动删除path:
  先offlne
  echo offline >/sys/block/device-name/device/state
  然后remove
  echo 1 >/sys/block/device-name/device/delete


主机识别存储设备标记主要有三个参数: 
C — Controller 
T — Target 
D — Disk 
主机识别存储上的设备就是依照这三个CTD的参数来识别的。 
换言之, 如果CTD相同,并且磁盘的signature(label in unix/linux)信息也相同,主机就会认为是同一个LUN。 
而CTD或是signature有任何一个参数发生变化, 操作系统就会认为是一个新的LUN。 


# 概念讲解
SCSI(Small Computer System Interface)小型计算机系统接口
lun的全称是logical unit number,也就是逻辑单元号
HBA的全称为Host Bus Adapter,即主机总线适配器
SATA(Serial Advanced Technology Attachment)即(串行高级技术附件,一种基于行业标准的串行硬件驱动器接口)
SAS(Serial Attached SCSI),串行连接SCSI接口,串行连接小型计算机系统接口
FC(Fibre Channel)光纤通道。是一种跟SCSI 或IDE有很大不同的接
IDE(Integrated Drive Electronics)即“电子集成驱动器”,它的本意是指把“硬盘控制器”与“盘体”集成在一起的硬盘驱动器

SCSI 参考网址

https://blog.51cto.com/u_15080020/4221032
https://zhuanlan.zhihu.com/p/560321850
https://www.cnblogs.com/timlong/p/6096173.html
https://www.cnblogs.com/timlong/p/6096202.html
点我回顶部

磁盘监控工具 --- iostat

# iostat [ -c | -d ] [ -k ] [ -t ] [ -V ] [ -x [ device ] ] [ interval  [ count ] ]
  其中,-c为汇报CPU的使用情况;-d为汇报磁盘的使用情况;-k表示每秒按kilobytes字节显示数据;-t为打印汇报的时间;-v表示打印出版本信息和用法;-x device指定要统计的设备名称,默认为所有的设备;interval指每次统计间隔的时间;count指按照这个时间间隔统计的次数。
# iostat 查看磁盘分区情况  
[root@localhost small_fio]# iostat -p /dev/sda
Linux 4.19.90-2102.2.0.0062.ctl2.x86_64 (localhost.localdomain)         05/26/2023      _x86_64_        (64 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.38    0.00    1.37    0.00    0.00   98.25
Device             tps    kB_read/s    kB_wrtn/s    kB_dscd/s    kB_read    kB_wrtn    kB_dscd
sda               0.46         3.76         2.55         0.00     275859     187497          0
sda1              0.01         0.09         0.00         0.00       6416          1          0
sda2              0.01         0.44         0.00         0.00      32653         32          0
sda3              0.45         3.19         2.55         0.00     234002     187464          0

 
硬盘SATA 1.0 的实际读写速率是150MB/s,带宽1.5Gb/s。
硬盘SATA 2.0的实际读写速率是300MB/s,带宽3Gb/s。
硬盘SATA 3.0的实际读写速率是600MB/s,带宽6Gb/s。
  

iostat 命令详解

点我回顶部

性能调优

NVME

for i in {0..11};do nvme set-feature /dev/nvme${i}n1 -feature-id 0x08 -value 0x0109;done

echo 0 > /proc/sys/kernel/perf_cpu_time_max_percent
echo 10000 >  /proc/sys/kernel/perf_event_max_sample_rate

FIO 调优网页参考

FIO 磁盘性能测试

FIO 配置文件压测

NUMA 配置详解

点我回顶部

HDD -- 固件更新

通用方法 ---- hdparm

# 通用方法,  Solidigm HDD 
os_disk_symbol=$(echo $(lsblk |grep -B1 -E "part|boot" |grep -E "^sd[a-z]+|^nvme" |awk '{print $1}') |sed 's/ /|/')
hdds=`lsblk | grep disk | awk '{print $1}' | grep -v ${os_disk_symbol}`
fw_file="skybolt_512E_back_compatible_CCA8.txt"
for dddd in ${hdds}
do
    echo "Starting FW Install Of:  /dev/${dddd}"
    hdparm --fwdownload ./7CV10111_7B1B0011_signed.bin --yes-i-know-what-i-am-doing --please-destroy-my-drive  /dev/${dddd}
done

其他厂商工具

# 西部数据固件升级---- Z:\Project\IT_RACK\Option\发布区\硬盘类工具
fw_file="V8GAW9G0.bin"
for dddd in `hugo s  | awk '/Ready/{print $4}'`
do
    echo "Starting FW Install Of: Serial: ${dddd}"
    hugo update -f ${fw_file} -s ${dddd}
    if [ $? -eq 0 ]; then
        echo "Device fw install is Successful : ${dddd}  --- ${fw_file}"
    else
        echo "Device fw install is Failed     : ${dddd}  --- ${fw_file}"
    fi
done

# SEAGATE SAS  HDD 盘固件升级方法
fw_file="skybolt_512E_back_compatible_CCA8.txt"
for dddd in `lsblk | grep '1.7T' | awk '{print $1}'`
do
    echo "Starting FW Install Of:  /dev/${dddd}"
    SeaChest_Lite_101_1183_64 --downloadFW ./${fw_file} -d ${dddd}
done


# 忆联盘固件升级如下: 
for dddd in ${nvmes}
do
    echo "Starting FW Install Of: Serial: ${dddd}"
    yes | umtool updatefw -d ${dddd} -f ${fw_file} -s 1 -a 1
    if [ $? -eq 0 ]; then
        echo "Device fw install is Successful : /dev/${dddd}  --- ${fw_file}"
    else
        echo "Device fw install is Failed     : /dev/${dddd}  --- ${fw_file}"
    fi
done

点我回顶部

NVME 工具详解 - - nvme

ledctl locate=/dev/rsnvmeX
# 查看序列号 
nvme id-ctrl /dev/nvmeX | grep -i sn   
# 使设备脱机 
sh -c"echo 0 >/sys/block/nvmeX/device/delete"  
# 查看设备列表信息 
nvme list
# 查看 smart 属性信息 
nvme smart-log <device>
# 查看 Error log 信息 
nvme error-log <device>
# 获取 日志 log 信息 
nvme get-log <device>
# 获取 fw-log 日志 
nvme fw-log <device>
# 查看设备控制器信息 
nvme id-ctrl <device>
# 设备控制器复位 
nvme reset <device>
# NVME 设备整盘格式化, 安全擦除 
nvme format <device> -s 0/1  # 其中 -s 0 表示高格, -s 1 表示低格
nvme format <device> -n 1 -s 0/1  # 指定 ns 格式化 

# 温度阈值
[root@localhost tmp02]# nvme get-feature /dev/nvme0n1   -feature-id 0x04
get-feature:0x4 (Temperature Threshold), Current value:0x00015f
# 队列数量
[root@localhost tmp02]# nvme get-feature /dev/nvme0n1   -feature-id 0x07
get-feature:0x7 (Number of Queues), Current value:0x7f007f
# 中断合并 
[root@localhost tmp02]# nvme get-feature /dev/nvme0n1   -feature-id 0x08
get-feature:0x8 (Interrupt Coalescing), Current value:00000000
# 异步事件配置
[root@localhost tmp02]# nvme get-feature /dev/nvme0n1   -feature-id 0x0b
get-feature:0xb (Async Event Configuration), Current value:0x000100

	

SSD --- 稳态配置

# 稳态顺序写 
fio --readwrite=write --bs=128k --iodepth=128 --numloop=2 -end_fsync=0 -group_reporting -direct=1 -ioengine=libaio -thread -buffer_compress_percentage=0 -invalidate=1 -np -randrepeat=0 -exitall --name=nvme2n1_write_fragment1 --filename=/dev/nvme2n1
# 稳态随机写 
fio --readwrite=randwrite --bs=4k --iodepth=128 --numjobs=4 --loop=2 -end_fsync=0 -group_reporting -direct=1 -ioengine=libaio -thread -buffer_compress_percentage=0 -invalidate=1 -norandommap -randrepeat=0 -exitall --filename=/dev/nvme3n1 --name=nvme3n1_randwrite_fragment2
点我回顶部

Smartctl ------ 工具详解

"/dev/hd[a-t]"    # IDE/ATA 磁盘
"/dev/sd[a-z]"    # SCSI devices磁盘。注意,对于SATA磁盘,由于是通过libata

选项及含义

选项 含义
-i 打印基本信息
-a 打印磁盘所有的SMART信息
-A 显示磁盘支持的厂商指定SMART特性
-x
-t 自检
-s smartctl 功能开关
-H 显示磁盘是否健康
--scan
-d 指定盘的类型

参考命令

# 打印自测和属性错误 
smartctl --attributes --log=selftest --quietmode=errorsonly /dev/sda
# 启用SMART
smartctl --smart=on --offlineauto=on --saveauto=on /dev/sda

# 打印基本信息(磁盘设备号、序列号、固件版本…)
smartctl -i /dev/sda
# 打印磁盘所有的SMART信息
smartctl -a /dev/sda
# 显示磁盘支持的厂商指定SMART特性。这些特性的编号从1-253,并且有指定的名字
smartctl -A /dev/sda
# 显示磁盘是否健康 
smartctl -H /dev/nvme0n1

# 显示硬盘错误汇总
smartctl -l error /dev/nvme0n1
	# 可设置的磁盘类型为:
     error             只显示error  log。
     selftest          只显示selftest  log
     selective         只显示selective  self-test  log
     directory         只显示Log  Directory
     background
     scttemp	
# smartctl -t short       # 后台检测硬盘,消耗时间短;
# smartctl -t long        # 后台检测硬盘,消耗时间长;
# smartctl -C -t short    # 前台检测硬盘,消耗时间短;
# smartctl -C -t long     # 前台检测硬盘,消耗时间长。
# smartctl -X             # 中断后台检测硬盘。

# 扫描所有磁盘
smartctl --scan
# 只扫描所有 NVME 盘 
smartctl --scan -d  nvme 
	# 可使用的类型如下: 
	ata, scsi[+TYPE], nvme[,NSID], sat[,auto][,N][+TYPE], usbcypress[,X], usbjmicron[,p][,x][,N], usbprolific, usbsunplus, sntjmicron[,NSID], intelliprop,N[+TYPE], jmb39x,N[,sLBA][,force][+TYPE], marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID, cciss,N, auto, test

网页参考

smartctl 输出详解

smartctl 命令解释

点我回顶部

显示磁盘和分区信息 --- lsblk

选项及含义

选项 含义
-d 只显示设备,不显示分区等
-p 显示完整路径
-l 以列表形式显示
-o 以指定格式输出设备和分区信息
-n 不打印表格标题
-x 指定表格中指定列进行排序
-t 以树形结构显示信息
-f 显示文件系统类型
-e 按照主要设备编号,排除指定类型设备,默认为 ram disk
-s 反向依赖输出,把树形结构倒过来
-S 只打印有关 scsi 设备的信息
-r 使用原始输出格式,非表格格式
-p 打印有关权限的信息
-I(大写的 i) 仅显示具有主要编号的设备
# 显示分区及逻辑卷的挂载点信息 
lsblk -pf 
for f in `lsblk -n -d -o 'NAME,MODEL,SERIAL' | grep MZ7L3480  | awk '{print $1}'`; do printf "${f}";printf " `smartctl -a /dev/$f|grep Fir|cut -d':' -f2 | xargs`\n"; done

lsblk -o 'NAME,MODEL' | grep -i samsung | awk '{print $1}' | xargs -i smartctl -a /dev/{} | grep -i firmware

lsblk -d -o 'NAME,MODEL,SERIAL,SIZE'

lsblk -l -d -o 'NAME,MODEL,SERIAL,SIZE,HCTL,UUID,STATE,ROTA,SCHED,RQ-SIZE,WWN,VENDOR,REV' -x HCTL
	NAME     # 设备名
	MODEL    # model 号, 截取固定长度 
	SERIAL   # 序列号 
	SIZE     # 大小
	HCTL     # SCSI ID  
	UUID     # 分区 UUID 
	STATE    # 状态 
	ROTA     # 是否是HDD, 若是 SSD 则该值为 0 , HDD 为 1 
	SCHED    # 磁盘调度算法 
	RQ-SIZE  #  
	WWN      
	VENDOR   # 厂商
	REV      # 固件 , 截图固定长度字符
	MAJ:MIN  # 是内核内部用来识别设备的编号,第一个数字表示类型为主要编号【不同的类型内核以规定好】, 第二个数字为次要编号,比如8表示scsi设备, 259 代表 NVME 设备,253 代表逻辑卷设备, 11 代表 rom 设备;
	MOUNTPOINT # 挂载点
	FSTYPE   # 文件系统类型
# 增加表格列信息
lsblk -d -o +rota
# 显式指定查看某一设备的信息
lsblk /dev/sda 
# 只显示指定编号的设备
lsblk -I 8 
# 只输出所有 NVME 盘的盘符
lsblk -o TRAN,NAME -d -n | awk '/^nvme /{print $2}' | xargs  
	# 等价于
	lsblk -I 259  -d -n -o NAME
# 排除 rom 设备和 NVME 设备,显示其他类型设备信息
lsblk -e 11 -e 259 -d -n
# 只输出所有 HDD 盘的盘符
lsblk -o ROTA,NAME -d -n | awk '{if($1 == "1"){print $2}}' | xargs
# 只打印输出 SCSI 设备盘符,包含 SCSI 逻辑设备
lsblk -d -I 8 -o NAME -n | xargs
# 只打印输出 rom 设备, 例如通过 KVM 挂载的设备  
lsblk -I 11 
# 只打印所有逻辑卷的卷路径
lsblk -s -I 253 -p -d -n -o NAME
# 输出设备的权限,属主属组信息
lsblk -m
# 查看主分区所在的设备路径 
lsblk -P -p -o NAME,MOUNTPOINT | awk '/MOUNTPOINT="\/"$/{print $0}' | cut -d'"' -f2
# 查看根分区和 boot 分区所在的内核主编号和次要编号 
lsblk -n -l -o MOUNTPOINTS,MAJ:MIN | awk '/^\/|\/boot/{print $2}' | xargs

Linux命令之lsblk命令

关于major、minor的解释

点我回顶部

其他


sftp指定端口连接:
sftp -oPort=10022 HA@10.1.2.3:/HA
ftp方式连接:
ftp   10.1.2.3  21
zip带密码解压缩到指定目录:
unzip -P passwd123 -o aaa.zip -d /data/
linux 乱码后解码:
echo -e '\xf'
查看占用端口:
netstat -anp |grep 9200
查看主机硬件时间:
hwclock -r
查看cpu核数:
nproc    (或 cat /proc/cpuinfo|grep processor|wc -l)

# 测试内存与缓存延迟的工具 
https://blog.csdn.net/qq_53169429/article/details/121296269

HGST(日立) 被 西数 收购了
Solidgm 被 SK Hynix(海力士) 收购了  

自动化脚本

性能测试脚本



Fio 数据自动解析脚本



Question &&& Solution

通过 DD 打 阵列卡驱动

8.3  OS安装过程中驱动更新方法
(1)        上述更新方法为常规OS下,如果在安装过程中无法识别阵列卡,需要先安装驱动,请按以下操作进行。
(2)        当前驱动文件夹中提供对应OS的dd.iso,将其挂载在KVM中。
(3)        开始OS引导,以RHEL7.6为例,进入选择菜单时,按e进入grub。
(4)        在linuxefi …行最后添加“linux dd”,按ctrl + x开始引导。
(5)        进入后会先选择驱动所在路径,选择挂载介质菜单选项,按空格选择,按c继续,根据提示继续操作,进入后即可安装OS。
或者用这个方法用dd包更新我放在100盘里的驱动试试
点我回顶部