直接提供脚本 虽然这个脚本是让 AI 帮忙写的,但经过实际验证,是有效的,并且我一直在使用
注意这的 1,2,3 步骤中的一些参数需要自己配置,比如时间范围,单位换算,文件路径等.
根据你实际情况改改,另外就是一些必备软件包得装一下,比如jq bc curl什么的.
最重要的是ITEM_ID这个变量,你需要从 zabbix 中找到你想计算 95 的流量图,然后把他的 itemid 拿出来.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 #!/usr/bin/env bash ZABBIX_URL="https://xxxxxxx/api_jsonrpc.php" ITEM_ID=" 123456" AUTH_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" TIME_FROM=1743436800 TIME_TILL=1746028799 BYTES_TO_MB=1048576 JSON_PATH="/tmp/zabbix.json" CSV_PATH="/tmp/zabbix_full_data.csv" ROW_PATH="/tmp/zabbix_row_data.csv" if [ ! -f "$JSON_PATH " ]; then echo "拉取 Zabbix 数据中..." RESPONSE=$(curl -s "$ZABBIX_URL " \ -H "Content-Type: application/json" \ --data-raw "{ \"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"history.get\", \"params\": { \"output\": \"extend\", \"itemids\": \"$ITEM_ID \", \"history\": 3, \"time_from\": $TIME_FROM , \"time_till\": $TIME_TILL , \"sortfield\": [\"clock\", \"itemid\"], \"sortorder\": \"ASC\" }, \"auth\": \"$AUTH_TOKEN \" }" ) echo "$RESPONSE " >"$JSON_PATH " else RESPONSE=$(awk 'NF' "$JSON_PATH " ) fi echo "Timestamp,Datetime,Value(MB)" >"$CSV_PATH " declare -A GROUPED_MAXwhile IFS= read -r line; do CLOCK=$(echo "$line " | jq -r '.clock' ) VALUE=$(echo "$line " | jq -r '.value' ) VALUE_MB=$(awk -v val="$VALUE " -v factor ="$BYTES_TO_MB " 'BEGIN {printf "%.2f", val / factor}' ) GROUP_TS=$((CLOCK / 300 * 300 )) if [[ -z "${GROUPED_MAX[$GROUP_TS]} " ]] || (($(echo "$VALUE_MB > ${GROUPED_MAX[$GROUP_TS]} " | bc -l))); then GROUPED_MAX[$GROUP_TS ]=$VALUE_MB fi DATETIME=$(date -d "@$CLOCK " "+%Y-%m-%d %H:%M:%S" ) echo "$DATETIME ,$VALUE_MB " >>"$ROW_PATH " done < <(echo "$RESPONSE " | jq -c '.result | sort_by(.clock)[]' )VALUES_MB=() for ts in $(printf "%s\n" "${!GROUPED_MAX[@]} " | sort -n); do val="${GROUPED_MAX[$ts]} " datetime=$(date -d "@$ts " "+%Y-%m-%d %H:%M:%S" ) echo "$ts ,$datetime ,$val " >>"$CSV_PATH " VALUES_MB+=("$val " ) done TOTAL=${#VALUES_MB[@]} if [[ $TOTAL -lt 1 ]]; then echo "未获取到有效数据,退出。" exit 1 fi SORTED=($(printf "%s\n" "${VALUES_MB[@]} " | sort -n)) PERCENTILE_INDEX=$(echo "$TOTAL * 0.95" | bc | awk '{printf("%d", ($1==int($1))?$1:$1+1)}' ) P95_VALUE=${SORTED[$((PERCENTILE_INDEX - 1))]} echo "✅ 数据点总数: $TOTAL " echo "📈 95 百分位位置: $PERCENTILE_INDEX " echo "📊 整体 95 值: $P95_VALUE MB" echo "📁 CSV 文件已生成: $CSV_PATH "
最终结果 大概长这样:
1 2 3 4 5 6 7 ✅ 数据点总数: 3589 📈 95 百分位位置: 3410 📊 整体 95 值: 1955.15 MB 📁 CSV 文件已生成: /tmp/zabbix_full_data.csv