nfsstat 是 Linux 中一个显示 NFS(Network File System)客户端和服务器统计信息的命令。它用于监控 NFS 性能、排查 NFS 相关问题,显示 NFS 和 RPC 调用的详细统计信息。
📖 基本语法
bash
nfsstat [选项]
重要特性:
- 显示 NFS 客户端统计信息
- 显示 NFS 服务器统计信息
- 显示 RPC 统计信息
- 支持重置统计计数器
- 显示详细的 NFS 调用统计
🎯 常用选项
| 选项 | 说明 |
|---|---|
-s |
显示 NFS 服务器统计信息。 |
-c |
显示 NFS 客户端统计信息。 |
-n |
显示 NFS 统计信息(客户端和服务器)。 |
-r |
显示 RPC 统计信息。 |
-o |
指定要显示的统计类别。 |
-z |
重置(清零)统计计数器。 |
-m |
显示挂载的 NFS 文件系统信息。 |
-2 |
显示 NFSv2 统计信息。 |
-3 |
显示 NFSv3 统计信息。 |
-4 |
显示 NFSv4 统计信息。 |
-l |
以列表格式显示。 |
-v |
显示详细输出。 |
-h |
显示帮助信息。 |
💡 核心用法示例
1. 基本统计信息
bash
# 显示所有 NFS 统计信息(客户端和服务器)
nfsstat
# 显示 NFS 客户端统计信息
nfsstat -c
# 显示 NFS 服务器统计信息
nfsstat -s
# 显示 NFS 客户端和服务器统计信息
nfsstat -cn
nfsstat -sn
# 显示 RPC 统计信息
nfsstat -r
# 显示所有统计信息
nfsstat -c -s -r
2. 按 NFS 版本显示
bash
# 显示 NFSv2 统计信息
nfsstat -2
# 显示 NFSv3 统计信息
nfsstat -3
# 显示 NFSv4 统计信息
nfsstat -4
# 显示特定版本的客户端统计
nfsstat -c -3
nfsstat -c -4
# 显示特定版本的服务器统计
nfsstat -s -3
nfsstat -s -4
3. 显示挂载信息
bash
# 显示挂载的 NFS 文件系统信息
nfsstat -m
# 显示特定挂载点的信息
mount | grep nfs
nfsstat -m | grep "/mnt/nfs"
# 显示详细的挂载信息
nfsstat -m -v
4. 重置统计信息
bash
# 重置所有 NFS 统计计数器
sudo nfsstat -z
# 重置 NFS 客户端统计
sudo nfsstat -c -z
# 重置 NFS 服务器统计
sudo nfsstat -s -z
# 重置 RPC 统计
sudo nfsstat -r -z
# 重置特定版本统计
sudo nfsstat -3 -z
sudo nfsstat -4 -z
5. 高级用法
bash
# 显示特定统计类别
nfsstat -o all # 显示所有类别
nfsstat -o net # 显示网络统计
nfsstat -o rpc # 显示 RPC 统计
nfsstat -o proc2 # 显示 NFSv2 过程统计
nfsstat -o proc3 # 显示 NFSv3 过程统计
nfsstat -o proc4 # 显示 NFSv4 过程统计
# 以列表格式显示
nfsstat -l
# 显示详细输出
nfsstat -v
# 组合使用多个选项
nfsstat -c -3 -l # 以列表格式显示 NFSv3 客户端统计
nfsstat -s -4 -v # 显示详细的 NFSv4 服务器统计
📊 输出解读
NFS 客户端统计示例
Client rpc stats:
calls retrans authrefrsh
125678 12 0
Client nfs v3:
null getattr setattr lookup access readlink
0 0% 1250 10% 45 0% 5678 45% 2345 19% 123 1%
read write create mkdir symlink mknod
3456 28% 234 2% 67 0% 12 0% 5 0% 0 0%
remove rmdir rename link readdir readdirplus
89 0% 4 0% 23 0% 8 0% 456 4% 567 5%
fsstat fsinfo pathconf commit
34 0% 12 0% 5 0% 45 0%
关键字段解释:
- calls:RPC 调用总数
- retrans:重传次数(高值可能表示网络问题)
- authrefrsh:认证刷新次数
- 各 NFS 操作百分比:显示每种操作的分布情况
NFS 服务器统计示例
Server rpc stats:
calls badcalls nullrecv badlen xdrcall
234567 12 0 5 3
Server nfs v3:
null getattr setattr lookup access readlink
0 0% 4567 19% 234 1% 12345 53% 3456 15% 123 0%
read write create mkdir symlink mknod
2345 10% 456 2% 89 0% 23 0% 5 0% 0 0%
remove rmdir rename link readdir readdirplus
67 0% 4 0% 34 0% 12 0% 234 1% 345 1%
fsstat fsinfo pathconf commit
23 0% 12 0% 5 0% 45 0%
关键字段解释:
- badcalls:错误的 RPC 调用数
- nullrecv:空接收数
- badlen:错误长度调用数
- xdrcall:XDR 解码错误数
RPC 统计示例
rcp:
calls badcalls retrans badxids timeouts wait newcred
345678 23 45 12 34 5 0
timers toobig nomem cantsend
12 3 0 2
🔧 实用场景示例
1. 监控 NFS 性能
bash
# 监控 NFS 客户端性能
watch -n 5 'nfsstat -c'
# 监控 NFS 服务器性能
watch -n 5 'nfsstat -s'
# 监控重传次数(网络问题指标)
watch -n 2 'nfsstat -c | grep -A1 "Client rpc stats"'
# 监控 NFSv4 性能
watch -n 5 'nfsstat -c -4'
# 监控特定操作的性能
watch -n 3 'nfsstat -c -3 | grep -E "(read|write)"'
2. 排查 NFS 问题
bash
# 检查重传率(高重传率表示网络问题)
nfsstat -c | awk '/^Client rpc stats:/ {getline; print "重传率:", $2/$1*100 "%"}'
# 检查错误调用率
nfsstat -s | awk '/^Server rpc stats:/ {getline; print "错误调用率:", $2/$1*100 "%"}'
# 检查认证问题
nfsstat -c | grep "authrefrsh"
# 检查超时情况
nfsstat -r | grep "timeouts"
# 检查网络缓冲区问题
nfsstat -r | grep -E "(toobig|nomem|cantsend)"
3. 性能分析脚本
bash
#!/bin/bash
# NFS 性能监控脚本
LOG_FILE="/var/log/nfs_performance.log"
INTERVAL=60 # 监控间隔(秒)
ALERT_THRESHOLD=5 # 重传率警报阈值(%)
ALERT_EMAIL="admin@example.com"
echo "开始 NFS 性能监控 $(date)" >> "$LOG_FILE"
echo "监控间隔: ${INTERVAL}秒" >> "$LOG_FILE"
echo "重传率警报阈值: ${ALERT_THRESHOLD}%" >> "$LOG_FILE"
echo "======================================" >> "$LOG_FILE"
monitor_nfs() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 获取客户端统计
local client_stats=$(nfsstat -c)
local server_stats=$(nfsstat -s)
local rpc_stats=$(nfsstat -r)
# 解析关键指标
local calls=$(echo "$client_stats" | awk '/^Client rpc stats:/ {getline; print $1}')
local retrans=$(echo "$client_stats" | awk '/^Client rpc stats:/ {getline; print $2}')
local badcalls=$(echo "$server_stats" | awk '/^Server rpc stats:/ {getline; print $2}')
local timeouts=$(echo "$rpc_stats" | awk '/^rpc:/ {getline; print $5}')
# 计算重传率
local retrans_rate=0
if [[ $calls -gt 0 ]]; then
retrans_rate=$(echo "scale=2; $retrans / $calls * 100" | bc)
fi
# 计算错误率
local error_rate=0
local server_calls=$(echo "$server_stats" | awk '/^Server rpc stats:/ {getline; print $1}')
if [[ $server_calls -gt 0 ]]; then
error_rate=$(echo "scale=2; $badcalls / $server_calls * 100" | bc)
fi
# 记录到日志
echo "[$timestamp] NFS 性能指标:" >> "$LOG_FILE"
echo " 客户端调用次数: $calls" >> "$LOG_FILE"
echo " 重传次数: $retrans" >> "$LOG_FILE"
echo " 重传率: ${retrans_rate}%" >> "$LOG_FILE"
echo " 服务器错误调用: $badcalls" >> "$LOG_FILE"
echo " 错误率: ${error_rate}%" >> "$LOG_FILE"
echo " RPC 超时次数: $timeouts" >> "$LOG_FILE"
# 检查操作分布(NFSv3 示例)
echo " NFSv3 操作分布:" >> "$LOG_FILE"
echo "$client_stats" | grep -A20 "Client nfs v3:" | head -20 >> "$LOG_FILE"
# 检查警报条件
if (( $(echo "$retrans_rate > $ALERT_THRESHOLD" | bc -l) )); then
echo "[警报] 重传率过高: ${retrans_rate}%" >> "$LOG_FILE"
echo "NFS 重传率异常: ${retrans_rate}% (阈值: ${ALERT_THRESHOLD}%)" | \
mail -s "NFS 性能警报 - $timestamp" "$ALERT_EMAIL"
fi
if [[ $timeouts -gt 10 ]]; then
echo "[警报] RPC 超时过多: $timeouts" >> "$LOG_FILE"
echo "RPC 超时次数异常: $timeouts" | \
mail -s "NFS RPC 超时警报 - $timestamp" "$ALERT_EMAIL"
fi
echo "--------------------------------------" >> "$LOG_FILE"
}
# 主循环
while true; do
monitor_nfs
sleep "$INTERVAL"
done
4. NFS 健康检查脚本
bash
#!/bin/bash
# NFS 健康检查脚本
CHECK_INTERVAL=300 # 检查间隔(秒)
LOG_FILE="/var/log/nfs_health.log"
ALERT_EMAIL="admin@example.com"
# NFS 挂载点列表
NFS_MOUNTS=(
"/mnt/nfs_share1"
"/mnt/nfs_share2"
"/data/nfs_backup"
"/home/nfs_homes"
)
echo "开始 NFS 健康检查 $(date)" >> "$LOG_FILE"
echo "检查间隔: ${CHECK_INTERVAL}秒" >> "$LOG_FILE"
echo "======================================" >> "$LOG_FILE"
check_nfs_health() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local issues_found=0
echo "[$timestamp] NFS 健康检查:" >> "$LOG_FILE"
# 1. 检查 NFS 挂载点
echo " 1. 挂载点检查:" >> "$LOG_FILE"
for mount_point in "${NFS_MOUNTS[@]}"; do
if mountpoint -q "$mount_point"; then
# 获取挂载信息
local mount_info=$(mount | grep " $mount_point ")
local nfs_version=$(echo "$mount_info" | grep -o "vers=[0-9.]*" | cut -d= -f2)
local mount_options=$(echo "$mount_info" | grep -o "\([^ ]*,\)*[^ ]*" | tail -1)
echo " ✓ $mount_point" >> "$LOG_FILE"
echo " 版本: NFSv${nfs_version:-未知}" >> "$LOG_FILE"
echo " 选项: ${mount_options}" >> "$LOG_FILE"
# 测试读写
local test_file="$mount_point/.nfs_test_$(date +%s)"
if touch "$test_file" 2>/dev/null; then
echo " 写测试: 正常" >> "$LOG_FILE"
rm -f "$test_file"
else
echo " 写测试: 失败" >> "$LOG_FILE"
((issues_found++))
fi
else
echo " ✗ $mount_point: 未挂载" >> "$LOG_FILE"
((issues_found++))
fi
done
# 2. 检查 NFS 统计信息
echo " 2. 统计信息检查:" >> "$LOG_FILE"
# 客户端统计
local client_stats=$(nfsstat -c 2>/dev/null)
if [[ -n "$client_stats" ]]; then
local retrans=$(echo "$client_stats" | awk '/^Client rpc stats:/ {getline; print $2}')
local calls=$(echo "$client_stats" | awk '/^Client rpc stats:/ {getline; print $1}')
if [[ $calls -gt 0 ]]; then
local retrans_rate=$(echo "scale=2; $retrans / $calls * 100" | bc)
echo " 客户端重传率: ${retrans_rate}%" >> "$LOG_FILE"
if (( $(echo "$retrans_rate > 5" | bc -l) )); then
echo " [警告] 重传率偏高" >> "$LOG_FILE"
((issues_found++))
fi
fi
else
echo " 客户端统计: 不可用" >> "$LOG_FILE"
fi
# 服务器统计(如果运行 NFS 服务器)
if systemctl is-active nfs-server >/dev/null 2>&1 || \
systemctl is-active nfs-kernel-server >/dev/null 2>&1; then
local server_stats=$(nfsstat -s 2>/dev/null)
if [[ -n "$server_stats" ]]; then
local badcalls=$(echo "$server_stats" | awk '/^Server rpc stats:/ {getline; print $2}')
local server_calls=$(echo "$server_stats" | awk '/^Server rpc stats:/ {getline; print $1}')
if [[ $server_calls -gt 0 ]]; then
local error_rate=$(echo "scale=2; $badcalls / $server_calls * 100" | bc)
echo " 服务器错误率: ${error_rate}%" >> "$LOG_FILE"
if (( $(echo "$error_rate > 1" | bc -l) )); then
echo " [警告] 错误率偏高" >> "$LOG_FILE"
((issues_found++))
fi
fi
fi
fi
# 3. 检查 RPC 服务
echo " 3. RPC 服务检查:" >> "$LOG_FILE"
local rpc_services=("rpcbind" "rpc.statd" "rpc.mountd")
for service in "${rpc_services[@]}"; do
if pgrep -x "$service" >/dev/null; then
echo " ✓ $service: 运行中" >> "$LOG_FILE"
else
echo " ✗ $service: 未运行" >> "$LOG_FILE"
((issues_found++))
fi
done
# 4. 检查网络连接
echo " 4. 网络连接检查:" >> "$LOG_FILE"
local nfs_ports=("2049" "111" "20048" "20049")
for port in "${nfs_ports[@]}"; do
if ss -tuln | grep -q ":$port "; then
echo " ✓ 端口 $port: 监听中" >> "$LOG_FILE"
else
echo " ✗ 端口 $port: 未监听" >> "$LOG_FILE"
((issues_found++))
fi
done
# 总结
echo " 5. 检查总结:" >> "$LOG_FILE"
if [[ $issues_found -eq 0 ]]; then
echo " ✓ 所有检查通过,NFS 状态正常" >> "$LOG_FILE"
else
echo " ✗ 发现 $issues_found 个问题" >> "$LOG_FILE"
# 发送警报邮件
echo "NFS 健康检查发现问题: $issues_found 个" | \
mail -s "NFS 健康检查警报 - $timestamp" "$ALERT_EMAIL"
fi
echo "--------------------------------------" >> "$LOG_FILE"
}
# 主循环
while true; do
check_nfs_health
sleep "$CHECK_INTERVAL"
done
5. NFS 性能优化监控
bash
#!/bin/bash
# NFS 性能优化监控脚本
LOG_FILE="/var/log/nfs_optimization.log"
INTERVAL=30 # 监控间隔(秒)
SAMPLE_COUNT=10 # 采样次数
ALERT_EMAIL="admin@example.com"
echo "开始 NFS 性能优化监控 $(date)" >> "$LOG_FILE"
echo "监控间隔: ${INTERVAL}秒" >> "$LOG_FILE"
echo "采样次数: ${SAMPLE_COUNT}" >> "$LOG_FILE"
echo "======================================" >> "$LOG_FILE"
# 性能基准测试函数
benchmark_nfs() {
local mount_point="$1"
local test_size_mb=100
local test_file="$mount_point/nfs_benchmark_$(date +%s).dat"
echo " 对 $mount_point 进行基准测试:" >> "$LOG_FILE"
# 写性能测试
local write_start=$(date +%s.%N)
dd if=/dev/zero of="$test_file" bs=1M count=$test_size_mb oflag=direct 2>/dev/null
local write_end=$(date +%s.%N)
local write_time=$(echo "$write_end - $write_start" | bc)
local write_speed=$(echo "scale=2; $test_size_mb / $write_time" | bc)
echo " 写速度: ${write_speed} MB/s" >> "$LOG_FILE"
# 读性能测试
local read_start=$(date +%s.%N)
dd if="$test_file" of=/dev/null bs=1M iflag=direct 2>/dev/null
local read_end=$(date +%s.%N)
local read_time=$(echo "$read_end - $read_start" | bc)
local read_speed=$(echo "scale=2; $test_size_mb / $read_time" | bc)
echo " 读速度: ${read_speed} MB/s" >> "$LOG_FILE"
# 清理测试文件
rm -f "$test_file"
# 返回速度值
echo "$write_speed $read_speed"
}
monitor_nfs_performance() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] NFS 性能监控:" >> "$LOG_FILE"
# 获取所有 NFS 挂载点
local nfs_mounts=$(mount -t nfs,nfs4 2>/dev/null | awk '{print $3}')
if [[ -z "$nfs_mounts" ]]; then
echo " 未找到 NFS 挂载点" >> "$LOG_FILE"
return
fi
# 对每个挂载点进行监控
for mount_point in $nfs_mounts; do
echo " 挂载点: $mount_point" >> "$LOG_FILE"
# 获取挂载选项
local mount_options=$(mount | grep " $mount_point " | grep -o "\([^ ]*,\)*[^ ]*" | tail -1)
echo " 挂载选项: $mount_options" >> "$LOG_FILE"
# 获取 NFS 版本
local nfs_version=$(mount | grep " $mount_point " | grep -o "vers=[0-9.]*" | cut -d= -f2)
echo " NFS 版本: v${nfs_version:-未知}" >> "$LOG_FILE"
# 获取统计信息
local client_stats=$(nfsstat -c 2>/dev/null)
# 分析操作分布
if [[ -n "$client_stats" ]]; then
# 获取读写操作比例
local read_ops=$(echo "$client_stats" | grep -A30 "Client nfs v${nfs_version:-3}:" | \
grep -E "^\s*read\s+" | awk '{print $2}' | tr -d '%')
local write_ops=$(echo "$client_stats" | grep -A30 "Client nfs v${nfs_version:-3}:" | \
grep -E "^\s*write\s+" | awk '{print $2}' | tr -d '%')
echo " 读操作比例: ${read_ops:-0}%" >> "$LOG_FILE"
echo " 写操作比例: ${write_ops:-0}%" >> "$LOG_FILE"
# 获取重传率
local calls=$(echo "$client_stats" | awk '/^Client rpc stats:/ {getline; print $1}')
local retrans=$(echo "$client_stats" | awk '/^Client rpc stats:/ {getline; print $2}')
if [[ $calls -gt 0 ]]; then
local retrans_rate=$(echo "scale=2; $retrans / $calls * 100" | bc)
echo " 重传率: ${retrans_rate}%" >> "$LOG_FILE"
# 重传率警报
if (( $(echo "$retrans_rate > 3" | bc -l) )); then
echo " [警告] 重传率偏高,可能存在网络问题" >> "$LOG_FILE"
echo "NFS 重传率警报: $mount_point 重传率 ${retrans_rate}%" | \
mail -s "NFS 网络问题警报 - $timestamp" "$ALERT_EMAIL"
fi
fi
fi
# 定期进行基准测试(每10次监控执行一次)
local sample_count_file="/tmp/nfs_sample_count_$(echo "$mount_point" | tr '/' '_')"
local current_count=$(cat "$sample_count_file" 2>/dev/null || echo "0")
if [[ $current_count -ge $SAMPLE_COUNT ]]; then
echo " 执行基准测试..." >> "$LOG_FILE"
benchmark_nfs "$mount_point"
echo "0" > "$sample_count_file"
else
echo " 跳过基准测试 (${current_count}/${SAMPLE_COUNT})" >> "$LOG_FILE"
echo $((current_count + 1)) > "$sample_count_file"
fi
echo "" >> "$LOG_FILE"
done
echo "--------------------------------------" >> "$LOG_FILE"
}
# 主循环
while true; do
monitor_nfs_performance
sleep "$INTERVAL"
done
⚠️ 重要注意事项
- 权限要求:查看统计信息通常不需要特殊权限,但重置统计需要 root 权限
- 统计重置:重置统计会清零所有计数器,影响历史数据分析
- 版本差异 :不同 Linux 发行版的
nfsstat输出格式可能略有不同 - NFSv4 差异:NFSv4 的统计信息与 NFSv3 有所不同
- 性能影响 :频繁运行
nfsstat对系统性能影响很小
🔄 相关命令
| 命令 | 说明 |
|---|---|
mount |
显示挂载信息,包括 NFS 挂载 |
showmount |
显示 NFS 服务器上的挂载信息 |
rpcinfo |
显示 RPC 服务信息 |
nfsiostat |
显示 NFS 挂载点的 I/O 统计(需要安装 nfs-utils) |
iotop |
显示进程级别的 I/O 统计 |
📌 最佳实践
- 定期监控:建立定期的 NFS 性能监控机制
- 基线建立:在系统正常时建立性能基线
- 警报设置:设置合理的警报阈值(如重传率 > 5%)
- 日志记录:记录历史统计信息用于趋势分析
- 版本升级:考虑升级到 NFSv4 以获得更好的性能和安全性
🎯 快速参考卡
基本查看:
nfsstat # 显示所有统计
nfsstat -c # 客户端统计
nfsstat -s # 服务器统计
nfsstat -r # RPC 统计
nfsstat -m # 挂载信息
按版本查看:
nfsstat -2 # NFSv2 统计
nfsstat -3 # NFSv3 统计
nfsstat -4 # NFSv4 统计
nfsstat -c -3 # NFSv3 客户端统计
重置统计:
sudo nfsstat -z # 重置所有统计
sudo nfsstat -c -z # 重置客户端统计
sudo nfsstat -s -z # 重置服务器统计
关键指标:
重传率 = retrans / calls * 100%
错误率 = badcalls / calls * 100%
操作分布:read, write, lookup 等
监控命令:
watch -n 5 'nfsstat -c' # 每5秒监控客户端
nfsstat -c | grep retrans # 检查重传次数
nfsstat -s | grep badcalls # 检查错误调用
nfsstat 是管理和优化 NFS 性能的重要工具,特别适合排查 NFS 相关的性能问题和网络问题。通过定期监控和分析统计信息,可以及时发现并解决 NFS 性能瓶颈。