最近服务器莫名IO爆炸寄了好几次,因此做了个脚本用于记录IO使用情况。
脚本名IO_Monitor.sh
nohup bash IO_Monitor.sh &
脚本会自动生成每日日志在指定目录(默认与脚本同目录)
#!/usr/bin/env bash
# =========================================
# IO监控脚本 - 通过 pidstat 记录 IO 使用情况
# 环境:CentOS Linux release 8.5.2111
# =========================================
# --------- 可调整参数(脚本最顶部声明) ---------
INTERVAL=10 # 循环间隔时间(秒),每隔多少秒记录一次
SAMPLE_INTERVAL=1 # pidstat 采样间隔(秒),pidstat 内部的间隔
SAMPLE_COUNT=1 # pidstat 采样次数,每次采样的次数
LOG_DIR="./" # 日志文件存放目录,默认当前目录
LOG_EMPTY=0 # 是否记录空输出(1=记录空输出及时间戳;0=仅记录有内容的采样)
# -----------------------------------------------
# 确保日志目录存在
mkdir -p "$LOG_DIR"
# 定义表头(包含取消写、I/O延迟)
HEADER="kB_rd/s kB_wr/s kB_ccwr/s UID PID iodelay Command"
# 无限循环记录
while true; do
# 日志文件按天分割:IOlogs-YYYY-MM-DD.log
LOG_FILE="$LOG_DIR/IOlogs-$(date +%F).log"
# 使用 pidstat -d 采集 IO 并过滤:跳过前3行,仅当 kB_rd/s、kB_wr/s 或 kB_ccwr/s 任一列为数字时输出
IO_OUTPUT=$(pidstat -d $SAMPLE_INTERVAL $SAMPLE_COUNT 2>/dev/null |
awk 'NR>3 && ($5 ~ /^[0-9]/ || $6 ~ /^[0-9]/ || $7 ~ /^[0-9]/) {
uid=$3; pid=$4; rd=$5; wr=$6; ccwr=$7; iodelay=$8;
cmd=""
for (i=9; i<=NF; i++) cmd = cmd $i " "
sub(/ $/, "", cmd)
printf("%s %s %s %s %s %s %s\n", rd, wr, ccwr, uid, pid, iodelay, cmd)
}')
# 仅在有实际内容,或 LOG_EMPTY=1 时记录
if [[ -n "$IO_OUTPUT" || $LOG_EMPTY -eq 1 ]]; then
# 打印时间戳
echo "=== $(date '+%Y-%m-%d %H:%M:%S') ===" >> "$LOG_FILE"
# 若有实际数据,先输出表头,再输出数据
if [[ -n "$IO_OUTPUT" ]]; then
echo "$HEADER" >> "$LOG_FILE"
echo "$IO_OUTPUT" >> "$LOG_FILE"
fi
fi
# 等待下一个周期(扣除 pidstat 采样间隔)
sleep $((INTERVAL - SAMPLE_INTERVAL))
done