| name | nfs-client-diagnosis |
| description | NFS 客户端故障诊断技能。覆盖 mount 挂载失败/hung、stale file handle、NFS4 lease 过期、 rpc.statd/lockd 异常、性能退化(rtt 飙升)、soft/hard mount 超时行为差异等场景。 当用户提到 NFS 挂载失败、NFS 文件操作卡死、ESTALE 错误、NFS 性能慢、NFS 锁问题、 nfs mount hang、nfs stale handle、rpc timeout、NFS server not responding 等关键词时, 必须使用本技能。支持双轨并行分析(系统状态逆向 + NFS 协议正向)并交叉验证。
|
NFS 客户端故障诊断(双轨:系统状态 + 协议推演)
第一节:故障目录结构
本技能诊断的对象是一台运行中的 Linux NFS 客户端系统。诊断所需数据全部来自客户端的运行时状态,无需离线文件。
NFS 客户端(故障系统) # 诊断现场
├── /proc/self/mountstats # 逐挂载点 NFS 操作详细统计 [READ/WRITE/GETATTR RTT]
├── /proc/net/rpc/nfs4.0/ # NFSv4 状态目录 [clientid/lease/slot_table/state/callback]
│ ├── clientid # NFSv4 clientid、lease 时间
│ ├── slot_table # slot 使用情况
│ ├── state # open/lock/delegation 状态计数
│ ├── callback # 回拨通道状态
│ └── delegreturn # delegreturn 统计
├── /proc/locks # 文件锁列表(NFS 锁标记)
├── /proc/net/rpc/ # RPC 统计 [nfs/nfsd/rpcrmt]
├── /var/lib/nfs/sm/ # statd 监控的主机列表
├── /var/log/messages # 系统日志
├── dmesg # 内核环形缓冲区
└── mount / findmnt # 当前 NFS 挂载状态
diagnosis_output/ # 基线脚本输出目录(自动生成)
├── nfs_mount_info.txt # NFS 挂载列表和参数
├── nfsstat_client.txt # NFS 客户端操作统计
├── nfs_mountstats.txt # 各挂载点详细统计
├── nfsv4_state.txt # NFSv4 状态
├── nfs_locks.txt # NFS 锁列表
├── rpc_services.txt # RPC 服务状态
├── dmesg_nfs.txt # 内核日志(NFS 相关)
└── journal_nfs.txt # journalctl 日志(NFS 相关)
第二节:分析策略(并行双轨,交叉验证)
系统状态逆向分析和 NFS 协议正向推演应同时进行,而非二选一。 两条轨道相互独立推进,最终交叉比对以确认根因。
┌─────────────────────────────────────────────────────────────────┐
│ 并行双轨分析模型 │
│ │
│ 轨道一:系统状态逆向 轨道二:协议逻辑正向 │
│ ──────────────────────── ───────────────────────── │
│ 从统计/日志出发,逆向推理 从 NFS 协议出发,正向追踪 │
│ │
│ 回答:系统状态如何? 回答:为什么故障? │
│ 异常指标在哪里? 协议链哪里断裂? │
│ │
│ ↓ ↓ │
│ └────────────── 交叉验证 ────────────┘ │
│ │
│ 见:第三节(统一分析流程:分支决策→双轨并行→交叉验证→输出) │
└─────────────────────────────────────────────────────────────────┘
两条轨道的分工与互补:
| 轨道一:系统状态逆向 | 轨道二:协议逻辑正向 |
|---|
| 优势 | 故障时刻的真实统计/日志数据、精确的错误计数、时序痕迹 | 完整因果模型、协议行为可见、故障传播路径可分析 |
| 局限 | 只有结果快照,过程不可见;统计可能被其他活动稀释 | 需要准确的挂载参数和协议版本;内核行为可能与协议规范有差异 |
| 典型盲区 | 静默数据损坏(soft mount EIO 未记录)、锁状态丢失 | 第三方驱动/NFS 实现与标准不一致(非标准 NFS 服务端) |
何时两条轨道都必须做:有明确故障现象时,两条轨道必须同时进行,最终通过交叉验证收敛到高置信度结论。
何时只能走单轨道:数据不完整时,仅走轨道一(系统状态逆向),但应明确标注分析局限性,并在结论中说明哪些环节依赖推断。
第三节:统一分析流程(分支决策 → 双轨并行 → 交叉验证 → 输出)
本节将"分支决策、轨道一(系统状态逆向)、轨道二(协议正向)、交叉验证"融合为一条可直接照做的统一流程。
执行约束:所有分析脚本的默认超时时间为 3 分钟(180s)。
Step 1:启动(基线信息收集 + 分支推荐)
运行:
bash scripts/01_baseline_info.sh -S "<故障开始时间>" [ -E "<故障结束时间>" ] [ -m <挂载点> ] [ -s <服务器> ]
记录输出中的四类关键信息(后续所有步骤围绕它们推进):
- NFS 挂载状态:挂载列表、挂载参数(vers/proto/timeo/retrans/soft/hard)
- NFS 操作统计:
nfsstat -c 错误计数(ESTALE/EXPIRED/BADSESSION)、nfsstat -r retrans/RTT
- NFSv4 状态:clientid/lease/slot_table/state/callback(
/proc/net/rpc/nfs4.0/)
- 异常日志:dmesg/journalctl 中 NFS/rpc/statd/lockd 关键告警
故障时间窗口确定规则(Step 1 执行前强制完成):
| 用户描述 | 时间窗口设定 |
|---|
| 明确时间点 | [故障时间 - 5分钟, 故障时间 + 持续时间 + 5分钟] |
| "刚才/刚刚" | [当前时间 - 30分钟, 当前时间] |
| "间歇性/偶尔" | [当前时间 - 2小时, 当前时间] |
| 无法确定 | [当前时间 - 1小时, 当前时间] |
先执行 date '+%Y-%m-%d %H:%M:%S' 确认当前时间,再计算绝对时间窗口。
Step 2:故障类型定界(选择分支脚本一键跑)
按 Step 1 输出推荐,执行对应分支脚本:
bash scripts/branch_X_xxx.sh [参数]
说明:每个 branch_*.sh 已内置系统状态采集命令序列(覆盖 S1–S4)。脚本输出的数据和诊断结论模板供 Step 3(轨道一)和 Step 4(轨道二)共同使用——轨道一基于输出数据做逆向归因,轨道二基于输出数据做协议正向推演。
若 Step 1 输出推荐多个分支脚本,必须按输出顺序全部执行,不可只选其一。
脚本对应执行参考如下:
异常信号 → 执行脚本
──────────────────────────────────────────────────────────────────────
mount 命令超时/报错 + rpcinfo 失败/端口不可达 → branch_A_mount_failure.sh <server> <export>
nfsstat 中 ESTALE 计数增长 + dmesg stale 记录 → branch_B_stale_handle.sh [mount_point] [file]
nfsstat 中 NFS4ERR_EXPIRED/BADSESSION + reclaim failed → branch_C_nfs4_lease.sh [mount_point] [server]
rpc.statd 未运行 + rpcinfo statd 注册缺失 + 锁操作失败 → branch_D_rpc_lockd.sh [server]
RPC retrans 增长 + mountstats RTT 高 + 用户感知慢 → branch_E_perf_degradation.sh [mount_point] [server]
挂载参数含 soft + 应用 EIO / hard + D 状态进程 → branch_F_mount_timeout.sh [mount_point]
Step 3:轨道一 —— 系统状态逆向(回答"系统状态如何 + 异常指标在哪里")
在分支脚本输出基础上,完成并固化四步证据链:
- S1 异常现场还原:确认故障现象、
nfsstat -c 错误类型、nfsstat -r retrans/RTT
- S2 统计/日志重建:用
mountstats + dmesg + journalctl 确认异常时间线和操作分布
- S3 数据状态验证:用
/proc/net/rpc/nfs4.0/ 验证 NFSv4 state、用 /proc/locks 验证锁状态
- S4 独立归因:仅基于系统状态客观数据,给出"异常值是什么、首次出现在哪个观测点、如何触发"
输出(供后续交叉验证使用):
异常观测点:<nfsstat 错误类型 / mountstats 操作>
关键指标值:<retrans 计数 / RTT 值 / 错误计数>
时间线:<异常首次出现时间 → 传播 → 当前状态>
系统状态归因假设:<一句话>
Step 4:轨道二 —— 协议逻辑正向(有协议分析时必做;回答"为什么故障 + 协议链哪里断裂")
P0:版本与参数验证(防止参数误判)
确认 Step 1 输出中的挂载参数:
- NFS 版本(vers=4.2/4.0/3)
- 传输协议(proto=tcp/udp)
- 超时参数(timeo/retrans/soft/hard)
- actimeo/acregmin/acregmax 等缓存参数
版本/参数不匹配的典型信号:
- 客户端请求 vers=4.2 但服务端仅支持 vers=3 → 协议降级错误
- soft mount 但应用未处理 EIO → 数据静默丢失
- timeo=10(1s)+ retrans=2 在网络抖动时频繁超时
参数不匹配时不停止:标注"参数差异",后续推断以实际行为校正。
P1–P2:以故障现象为入口,完成"现象-协议链对齐"(关键桥梁)
- P1 锚定入口:取 Step 3 的异常观测点,定位到对应的 NFS 协议操作(mount/READ/WRITE/GETATTR/LOCK/OPEN)
- P2 对齐确认:以 NFS 协议规范为标准理解预期行为,区分"协议正常行为"和"异常行为"
常见协议陷阱与处理:
| 陷阱场景 | 现象 | 应对方式 |
|---|
| soft mount EIO | write 返回成功但数据未落盘 | 检查 write 的 mountstats RTT,看是否超时 |
| NFSv4 lease 到期 | 操作卡死后自动恢复 | 检查 reclaim 日志和 state 恢复时间线 |
| RPC 重试 vs 新请求 | retrans 高不一定是网络丢包 | 区分 mountstats 中 retrans 和 timeouts |
| statd 监控丢失 | 锁操作无法恢复 | 检查 sm/ 和 sm.bak/ 目录一致性 |
P3:故障链逐环节推演(不允许省略链路)
原则:从故障现象出发,沿 NFS 协议栈逐层向下(应用 → VFS → NFS 客户端 → RPC → TCP/IP → 网络),逐层完成三件事:
① 找到对应协议层和操作
② 用 Step 3 的系统状态数据验证该层的输入/输出是否异常
③ 判断:该层是"表现层(故障呈现)"还是"根因层(异常引入)"?
表现层 vs 根因层必须严格区分:表现层是故障链的终点(如应用报 EIO),根因层是异常最初引入点(如网络丢包导致 RPC 超时)。
P4:反事实验证(强制;不能止步于"找到可疑指标")
用协议链根因假设正向推演,并与系统状态数据逐条对齐:
✓ 推演的异常类型 == nfsstat 中的错误统计?
✓ 推演的异常时间 == 日志时间戳和 mountstats 时间线?
✓ 推演的故障传播路径 == 用户描述的现象?
三条全 ✓ 才能判定"根因确认"。
协议正向输出格式:
故障模式:<mount失败/stale/lease过期/lockd异常/性能退化/超时>
协议层:<mount/RPC/NFSv4 STATE/NLM/应用层>
根因协议环节:<精确描述>
触发条件:<前置状态>
因果链:[协议异常引入] → [传播] → [用户可见故障]
Step 5:交叉验证(双轨汇合,冲突仲裁,置信度收敛)
对每条证据做对齐检查:
| 验证维度 | 轨道一(系统状态)结论 | 轨道二(协议正向)结论 | 是否吻合? |
|---|
| 故障现象 | nfsstat 中 <错误类型> | 协议链分析得出 <故障模式> | □ 吻合 □ 不符 |
| 异常指标 | mountstats 中 <指标值> | 协议层推演预期产生此值 | □ 吻合 □ 不符 |
| 时间线 | 日志时间戳 <T0>→<T1> | 协议异常应在 <T0> 引入 | □ 吻合 □ 不符 |
| 根因环节 | 首次异常观测点 <观测点> | 对应协议层存在缺陷 | □ 吻合 □ 不符 |
| 触发条件 | 并发/输入特征 | 协议在此条件下异常触发 | □ 吻合 □ 不符 |
不一致时的仲裁原则:
异常指标:优先信任 mountstats/nfsstat(客观事实)
时间线不符:优先检查系统时区和 NTP 同步状态
根因环节不符:保留多假设并补证据(必要时抓包复现)
置信度收敛:
- 高:两轨完全吻合 + 反事实验证通过
- 中:两轨基本吻合,但有 1 个维度依赖推断;或仅完成轨道一
- 低:两轨存在矛盾且无法解释;或证据链缺失超过两环节
- 疑似服务端:两轨客户端证据链均不完整 + 症状指向服务端
常见误判陷阱(用于复核结论质量):
- 多个 NFS 挂载点混淆:不同挂载点可能使用不同版本和参数,诊断时必须区分。一个挂载点的故障不代表所有 NFS 都有问题。
- 客户端 vs 服务端问题混淆:
nfsstat -c(客户端统计)和 nfsstat -s(服务端统计)必须区分。Agent 在客户端上只能查看 -c 输出。
- NFSv3 vs NFSv4 锁机制混淆:NFSv3 使用 NLM(rpc.statd/lockd),NFSv4 使用 lease 内建锁机制,两者诊断路径完全不同。
- 网络延迟 vs NFS 服务器延迟的区分:
ping RTT 反映网络延迟,mountstats 中的 READ/WRITE RTT 反映完整 IO 延迟(含服务器处理时间)。两者差异大说明服务器是瓶颈。
- soft mount 静默失败:soft mount 超时返回 EIO,应用不检查返回值会静默丢数据——这不是 NFS 的 Bug,而是应用层设计问题。Agent 需要明确区分故障责任归属。
- stale file handle ≠ 文件丢失:文件可能在服务端仍然存在,但文件句柄指向的 inode 已变化(如目录被 rm -rf 后重建)。需要区分"文件真的没了"还是"句柄过期了"。
- D 状态进程不可杀的内核限制:hard mount + server 不响应时,进程进入 D 状态(TASK_UNINTERRUPTIBLE),SIGKILL 也无法杀死。这不是 NFS Bug,是 Linux 内核 IO 模型的行为特征。
软件 vs 服务端的判断原则:
客户端故障优先,但以下情况提升服务端怀疑优先级:
① 多次随机 ESTALE,位置不同,无法解释
② 所有客户端同时出现相同症状
③ NFS 服务端近期有重启/变更记录
→ 需联系服务端管理员确认 export/NFS 服务状态
Step 6:最终输出(按第九节模板落盘)
将 Step 3/4/5 的输出填入第九节报告结构,并显式写清:结论、证据链、排除项、修复建议、验证建议。
第四节:轨道一 —— 系统状态逆向分析
本节已合并进第三节的统一分析流程(Step 3)。
第五节:轨道二 —— NFS 协议正向推演
本节已合并进第三节的统一分析流程(Step 4)。
第六节:交叉验证与结论收敛(双轨汇合)
本节已合并进第三节的统一分析流程(Step 5)。
第七节:故障类型决策树(两条轨道共用)
本节内容已合并进第三节的统一分析流程(Step 2)。
第八节:注意事项与置信度评级
本节内容已合并进第三节的统一分析流程(Step 5)。
第九节:最终报告结构
## 1. 故障概要
| 项目 | 内容 |
| ---- | ---- |
| 故障时间窗口 | <开始时间 - 结束时间> |
| 诊断执行时间 | <执行时间> |
| 影响范围 | <受影响 NFS 挂载点/服务/应用> |
| 故障模式 | <分支A/B/C/D/E/F> |
| 置信度 | <高/中/低/疑似服务端> |
## 2. 故障路径分析
[根因节点] → [传播路径] → [用户可见现象]
- **触发点**:最初触发故障的关键事件
- **传播路径**:故障如何从根因扩散到用户可见
- **最终影响**:用户或业务最终可见的异常
## 3. 诊断证据链
### 轨道一(系统状态)结论
- 异常观测点:<nfsstat 错误类型 / mountstats 操作>
- 关键指标值:<retrans/RTT/错误计数>
- 时间线:<异常首次出现时间 → 传播 → 当前状态>
- 系统状态侧根因假设:<基于系统状态的反推>
### 轨道二(协议正向)结论
- 故障模式:<mount失败/stale/lease过期/lockd异常/性能退化/超时>
- 根因协议环节:<精确描述>
- 触发条件:<前置状态>
- 因果链:[协议异常引入] → [传播] → [用户可见故障]
### 交叉验证结果
- 故障现象吻合:□ 是 □ 否(<说明>)
- 异常指标吻合:□ 是 □ 否(<说明>)
- 时间线吻合: □ 是 □ 否(<说明>)
- 根因环节吻合:□ 是 □ 否(<说明>)
- 触发条件吻合:□ 是 □ 否(<说明>)
- 综合判断:<两轨结论是否一致,若有矛盾如何解释>
## 4. 排除的替代假设
- <假设A>:排除原因 <...>
- <假设B>:排除原因 <...>
## 5. 修复建议
> 仅提供建议,禁止自动执行。所有高危操作必须标注 🔴 并提供回滚方案。
### 5.1 立即修复(快速止血)
- **建议 1**:<描述> —— 🔴/🟡/🟢
- 操作命令:<命令>
- 风险提示:<具体风险>
- 回滚方案:<高危必填>
- 执行前提:<确认条件>
### 5.2 根本修复
- **建议 2**:<描述> —— 🔴/🟡/🟢
- 操作命令:<命令>
- 回滚方案:<高危必填>
### 5.3 预防措施
- 监控建议:<监控项和阈值>
- 配置建议:<优化配置项>
- 巡检建议:<定期检查项>
## 6. 验证建议
- 如何确认根因:<验证方法>
- 如何验证修复有效:<验证方法>
第十节:参考文件
references/nfs_diagnosis_commands.md:NFS 诊断命令速查手册
references/nfs_error_codes.md:NFS 关键错误码与日志关键字参考
scripts/01_baseline_info.sh:基线全量信息采集脚本
scripts/branch_A_mount_failure.sh:分支A —— mount 挂载失败/hung 诊断脚本
scripts/branch_B_stale_handle.sh:分支B —— stale file handle 诊断脚本
scripts/branch_C_nfs4_lease.sh:分支C —— NFSv4 lease 过期/state 恢复诊断脚本
scripts/branch_D_rpc_lockd.sh:分支D —— rpc.statd/lockd 异常诊断脚本
scripts/branch_E_perf_degradation.sh:分支E —— 性能退化(rtt 飙升)诊断脚本
scripts/branch_F_mount_timeout.sh:分支F —— soft/hard mount 超时行为差异诊断脚本