Last active
September 18, 2025 02:18
-
-
Save githubhjs/c1398c18dc6cd65a2852c774971008f9 to your computer and use it in GitHub Desktop.
① mountstats 解析器(無需 sudo) 功能:取樣兩次 /proc/self/mountstats(或用 nfsiostat 若系統有),輸出每個 NFS 掛載點的 ops/s(讀/寫)、avg RTT / avg exe、rpc bklog、以及「初步瓶頸判定」。 把下面存成 nfs-mountstats-lite.sh,給執行權限(不需 sudo):
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # nfs-mountstats-lite.sh -- user-space NFS health snapshot | |
| # 用法:./nfs-mountstats-lite.sh [-i interval_sec] [-c samples] | |
| # 預設 interval=2, samples=3(總觀察 ~4 秒) | |
| set -euo pipefail | |
| INT=2; CNT=3 | |
| while getopts "i:c:" o; do | |
| case "$o" in | |
| i) INT="$OPTARG";; | |
| c) CNT="$OPTARG";; | |
| esac | |
| done | |
| have_nfsiostat=0 | |
| command -v nfsiostat >/dev/null 2>&1 && have_nfsiostat=1 | |
| ts() { date "+%F %T"; } | |
| echo "[$(ts)] host=$(hostname) interval=${INT}s samples=${CNT}" | |
| echo "---- NFS mounts ----" | |
| grep -E ' nfs[34]? ' /proc/mounts || true | |
| echo | |
| if [ "$have_nfsiostat" -eq 1 ]; then | |
| echo "nfsiostat 可用:匯總顯示(含 avg RTT/exe、bklog,使用者權限即可)" | |
| echo "------------------------------------------------------------------" | |
| nfsiostat -h "$INT" "$CNT" | awk ' | |
| BEGIN{FS=":"} | |
| /^\/|^[A-Za-z0-9\.\-]+:\/.* mounted on /{ | |
| gsub(" mounted on ", " -> "); | |
| print "\n[FS] " $0 | |
| } | |
| /avg RTT/ || /avg exe/ || /rpc bklog/ || /read:/ || /write:/ { | |
| gsub(/^[ \t]+/,"",$0); print " " $0 | |
| }' | |
| echo | |
| else | |
| echo "找不到 nfsiostat,改以 mountstats 粗解析(字段較原始)" | |
| echo "------------------------------------------------------------------" | |
| snap() { grep -A200 -E '^device .+ nfs' /proc/self/mountstats; } | |
| TMP1=$(mktemp); TMP2=$(mktemp) | |
| snap >"$TMP1"; sleep "$INT"; snap >"$TMP2" | |
| # 只做最保守的統計:READ/WRITE 總次數差值 ≈ ops/s;其餘給出原始片段供觀察 | |
| awk -v intv="$INT" ' | |
| function flush(){ | |
| if (dev!=""){ | |
| rops = r2 - r1; wops = w2 - w1; | |
| printf "\n[FS] %s -> %s\n", dev, mnt; | |
| if (rops || wops){ | |
| printf " ops/s (READ/WRITE): %.2f / %.2f\n", rops/intv, wops/intv; | |
| } else { | |
| print " ops/s: (無差值,可能閒置)" | |
| } | |
| print " *以下為原始 mountstats 片段(找 avg rtt/exe、rpc bklog 關鍵詞)" | |
| for(i=0;i<lines;i++) print " " buf[i]; | |
| } | |
| dev=""; mnt=""; r1=r2=w1=w2=0; lines=0; | |
| } | |
| FNR==1 { pass++ } | |
| /^device .* nfs/{ | |
| flush() | |
| dev=$2; mnt=$5; next | |
| } | |
| /READ:/{ | |
| # 嘗試抓「ops」欄(不同核心格式不同,僅保守匹配第一個數字為 ops) | |
| if (pass==1){split($0,a,/[ :]+/); for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+$/){r1+=$i; break}} | |
| else {split($0,a,/[ :]+/); for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+$/){r2+=$i; break}} | |
| } | |
| /WRITE:/{ | |
| if (pass==1){split($0,a,/[ :]+/); for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+$/){w1+=$i; break}} | |
| else {split($0,a,/[ :]+/); for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+$/){w2+=$i; break}} | |
| } | |
| { | |
| if (pass==2 && lines<20){ buf[lines]=$0; lines++ } # 帶 20 行上下文協助人工判讀 | |
| } | |
| END{ flush() } | |
| ' "$TMP1" "$TMP2" | |
| rm -f "$TMP1" "$TMP2" | |
| echo | |
| fi | |
| echo "---- 客戶端 RPC 統計(重傳/逾時) ----" | |
| nfsstat -c -o net -o rpc 2>/dev/null || echo "(nfsstat 不可用)" | |
| echo | |
| echo "初步判定指南:" | |
| echo " exe ≫ rtt → 伺服器/後端 I/O 在忙;rtt 高且 retrans/timeout 升 → 網路路徑;" | |
| echo " rpc bklog 持續 >0 或連線數偏少 → 客戶端並行度不足(nconnect/應用多執行緒)。" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment