You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写Bash脚本统计3个进程1分钟磁盘读取量:读取值恒为0求助

问题分析与解决办法

核心问题原因

你之前的思路错误在于直接累加/proc/$pid/io中的read_bytes值——这个字段是进程从启动到当前的累计读取字节数,不是每秒的增量。如果进程在监控期间没有读取操作,每次读取的数值都一样,累加后相当于初始值重复加60次;如果初始值为0且进程无读写行为,结果自然是0。另外,如果进程提前退出,/proc/$pid/io会消失,grep返回空后awk输出0,也会导致结果异常。

正确实现思路

  1. 先记录每个目标进程的初始read_bytes值、PID和启动命令行;
  2. 持续监控60秒,期间可每秒检查进程状态(避免进程退出后报错);
  3. 60秒后读取每个进程的最终read_bytes值,用最终值减去初始值,得到该进程1分钟内的实际读取字节数;
  4. 按要求格式输出结果。

完整脚本示例

#!/bin/bash

# 定义要监控的三个进程(可替换为具体PID或进程名)
# 若用进程名,需确保每个名称唯一匹配单个进程,否则调整pgrep逻辑
TARGET_PROCESSES=("nginx" "mysql" "php-fpm")

# 存储进程初始数据:格式为 "PID:COMMAND:INIT_READ"
declare -a PROC_DATA

# 采集初始数据
for proc_name in "${TARGET_PROCESSES[@]}"; do
    pid=$(pgrep -o "$proc_name")
    if [ -z "$pid" ]; then
        echo "警告:未找到进程 $proc_name"
        continue
    fi
    # 处理/proc/cmdline的null分隔符,转为正常命令行格式
    cmd=$(cat /proc/$pid/cmdline | tr '\0' ' ')
    init_read=$(grep "read_bytes:" /proc/$pid/io 2>/dev/null | awk '{print $2}')
    if [ -z "$init_read" ]; then
        echo "警告:无法获取进程 $pid 的初始读取数据"
        continue
    fi
    PROC_DATA+=("$pid:$cmd:$init_read")
done

# 监控60秒
end_time=$((SECONDS + 60))
while [ $SECONDS -lt $end_time ]; do
    sleep 1
    # 可选:此处可添加进程存活检查,提前标记退出的进程
done

# 计算最终读取量并输出
echo "PID:启动命令行:读取数据量"
for data in "${PROC_DATA[@]}"; do
    pid=$(echo "$data" | cut -d: -f1)
    cmd=$(echo "$data" | cut -d: -f2-)
    init_read=$(echo "$data" | cut -d: -f3)
    
    final_read=$(grep "read_bytes:" /proc/$pid/io 2>/dev/null | awk '{print $2}')
    if [ -z "$final_read" ]; then
        echo "$pid:$cmd:进程已退出"
        continue
    fi
    
    total_read=$((final_read - init_read))
    echo "$pid:$cmd:$total_read"
done

关键细节说明

  • 进程匹配:脚本用pgrep -o获取进程名对应的首个PID,若已知具体PID,可直接把TARGET_PROCESSES改成PID列表,比如TARGET_PROCESSES=("1234" "5678" "9012");
  • 命令行处理:/proc/$pid/cmdline用null分隔字段,通过tr '\0' ' '转换为空格分隔的正常命令行;
  • 进程退出处理:若进程在监控期间退出,脚本会输出“进程已退出”,避免报错;
  • 数值计算:用final_read - init_read得到1分钟内的实际读取量,这是正确的统计方式,而非累加每秒的累计值。

测试验证

如果测试进程确实无读取操作,结果为0是正常的。可手动触发进程读取行为(比如用cat large_file作为测试进程),再运行脚本验证结果是否正确。

内容的提问来源于stack exchange,提问作者oselish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 23:03:27