NFS/故障排除
关于常见问题和解决方案的专门文章。
服务器端问题
exportfs: /etc/exports:2: 语法错误:错误的选项列表
确保删除 /etc/exports
中选项列表中的所有空格。
exportfs: NFS 导出需要 fsid=
由于并非所有文件系统都存储在设备上,并且并非所有文件系统都具有 UUID(例如 FUSE),因此有时需要显式告知 NFS 如何识别文件系统。这可以通过 fsid
选项完成
/etc/exports
/srv/nfs client(rw,sync,crossmnt,fsid=0) /srv/nfs/music client(rw,sync,fsid=10)
用户组/GID 权限问题
如果 NFS 共享挂载正常,并且所有者可以完全访问,但组成员无法访问;请检查用户所属的组数。NFS 对用户可以所属的组数限制为 16 个。如果您的用户超过此数量,则需要在 NFS 服务器上启用 manage-gids
启动标志
/etc/nfs.conf
[mountd] manage-gids=y
尝试以 root 身份写入文件时出现“权限被拒绝”
- 如果需要以 root 身份挂载共享,并从客户端获得完全的 r/w 访问权限,请将 no_root_squash 选项添加到
/etc/exports
中的导出中
/var/cache/pacman/pkg 192.168.1.0/24(rw,no_subtree_check,no_root_squash)
- 您还必须将 no_root_squash 添加到
/etc/exports
中的第一行
/ 192.168.1.0/24(rw,fsid=root,no_root_squash,no_subtree_check)
执行 showmount -e 命令时出现“RPC: 程序未注册”
确保 nfs-server.service
和 rpcbind.service
在服务器端运行,请参阅 systemd。如果它们未运行,请启动并启用它们。
还要确保启用 NFSv3。showmount 不 适用于仅 NFSv4 的服务器。
UDP 挂载不起作用
nfs-utils 在 2.2.1 版本中禁用了通过 UDP 提供 NFS 服务。Arch core 于 2017 年 12 月 21 日更新至 2.3.1(跳过了 2.2.1。)如果 UDP 停止工作,请在 /etc/nfs.conf
的 [nfsd]
下添加 udp=y
。然后重启 nfs-server.service
。
大目录超时
自 nfs-utils 1.0.x 版本以来,每个子目录都会检查权限。这可能会导致具有“大量”子目录的目录超时,即使只有几百个。
要禁用此行为,请将选项 no_subtree_check
添加到 /etc/exports
中的共享目录。
客户端问题
mount.nfs4: 没有此设备
确保已加载 nfsd
内核模块。
mount.nfs4: 无效参数
启用 并 启动 nfs-client.target
,并确保相应的守护程序(nfs-idmapd、rpc-gssd 等)在服务器上运行。
mount.nfs4: 网络不可达
使用 systemd-networkd 或 NetworkManager 的用户可能会注意到 NFS 挂载在启动时未挂载。
通过启用 systemd-networkd-wait-online.service
或 NetworkManager-wait-online.service
,强制网络完全配置。这可能会减慢启动过程,因为并行运行的服务较少。
NetworkManager-wait-online.service
,请在您的网络配置文件中设置 ipv4.may-fail=no
,以确保在到达 NetworkManager-wait-online.service
之前获取 IPV4 地址。mount.nfs4: 指定了不正确的挂载选项
如果在使用 sec=krb5
选项时没有运行 nfs-client.target
和/或 rpc-gssd.service
,则可能会发生这种情况。启动并启用这些服务应能解决问题。
无法从 OS X 客户端连接
当尝试从 OS X 客户端连接时,您将看到服务器日志中的一切正常,但 OS X 将拒绝挂载您的 NFS 共享。您可以执行以下两件事之一来解决此问题
- 在 NFS 服务器上,将
insecure
选项添加到/etc/exports
中的共享中,然后重新运行exportfs -r
。
... 或 ...
- 在 OS X 客户端上,将
resvport
选项添加到mount
命令行。您也可以在/etc/nfs.conf
中将resvport
设置为默认客户端挂载选项
/etc/nfs.conf
nfs.client.mount.options = resvport
使用默认客户端挂载选项也应影响通过 Finder 通过“连接到服务器...”挂载共享。
来自 OS X 客户端的连接不可靠
OS X 的 NFS 客户端针对 OS X 服务器进行了优化,可能在 Linux 服务器上出现一些问题。如果您遇到性能缓慢、频繁断开连接以及国际字符问题,请通过将行 nfs.client.mount.options = intr,locallocks,nfc
添加到 Mac 客户端上的 /etc/nfs.conf
来编辑默认挂载选项。有关挂载选项的更多信息,请参见 OS X mount_nfs(8)。
客户端间歇性冻结,在复制大文件时
如果您从客户端计算机复制大文件到 NFS 服务器,传输速度非常快,但几秒钟后速度下降,并且您的客户端计算机间歇性完全锁定一段时间,直到传输完成。
尝试在客户端上添加 sync
作为挂载选项(例如在 /etc/fstab
中)以解决此问题。
mount.nfs: 操作不允许
NFSv4
如果您使用 Kerberos (sec=krb5*
),请确保客户端和服务器时钟正确。建议使用 ntpd 或 systemd-timesyncd。此外,检查客户端上解析的服务器规范名称(请参阅 域名解析)是否与服务器 NFS 主体中的名称匹配。
NFSv3 及更早版本
nfs-utils 1.2.1-2 或更高版本默认使用 NFSv4,导致 NFSv3 共享在升级时失败。问题可以通过在命令行上使用挂载选项 'vers=3'
或 'nfsvers=3'
来解决
# mount.nfs remote target directory -o ...,vers=3,... # mount.nfs remote target directory -o ...,nfsvers=3,...
或在 /etc/fstab
中
remote target directory nfs ...,vers=3,... 0 0 remote target directory nfs ...,nfsvers=3,... 0 0
mount.nfs: 协议不支持
当您在 NFS 源的路径中包含导出根目录时,会发生此错误。例如
# mount SERVER:/srv/nfs4/media /mnt mount.nfs4: Protocol not supported
请使用相对路径代替
# mount SERVER:/media /mnt
权限问题
如果您发现无法正确设置文件权限,请确保客户端和服务器上都存在用户/用户组。
如果您的所有文件都归 nobody
所有,并且您正在使用 NFSv4,则在客户端和服务器上,您都应确保已启动 nfs-idmapd.service
。
在某些系统上,从 FQDN 减去主机名来检测域似乎无法可靠地工作。如果在上述更改后文件仍然显示为 nobody
,请编辑 /etc/idmapd.conf
,确保将 Domain
设置为 FQDN 减去主机名
。例如
/etc/idmapd.conf
[General] Domain = domain.ext [Mapping] Nobody-User = nobody Nobody-Group = nobody [Translation] Method = nsswitch
Vagrant 和 synced_folders 的问题
如果您收到有关不支持协议的错误,则需要在主机上启用通过 UDP 的 NFS(或使 Vagrant 使用通过 TCP 的 NFS。)请参阅 #UDP 挂载不起作用。
如果 Vagrant 脚本无法通过 NFS 挂载文件夹,则安装 net-tools 软件包可能会解决问题。
性能问题
此 NFS Howto 页面 提供了一些关于性能的有用信息。以下是一些其他提示
诊断问题
- Htop 应该是您的首选。最明显的症状将是 CPU 使用率达到最大值。
- 按 F2,然后在“显示选项”下,启用“详细 CPU 时间”。按 F1 查看 CPU 条中使用的颜色的说明。特别是,CPU 的大部分时间是用于响应 IRQ,还是在等待 I/O (wio)?
关闭时打开/关闭时刷新
症状: 您的客户端正在写入许多小文件。服务器 CPU 没有达到最大值,但等待 I/O 非常高,并且服务器磁盘似乎比您预期的更频繁地转动。
为了确保跨客户端的数据一致性,NFS 协议要求在写入后关闭文件时,客户端的缓存会被刷新(所有数据都推送到服务器)。由于服务器不允许缓冲磁盘写入(如果服务器崩溃,客户端将不会意识到数据未正确写入),因此数据会在客户端的请求完成之前立即写入磁盘。当您从客户端写入大量小文件时,这意味着服务器的大部分时间都花在等待小文件写入其磁盘,这可能会导致吞吐量显着降低。
有关关闭时打开策略的更多详细信息,请参阅 这篇优秀的文章 或 nfs 手册页。有几种方法可以解决此问题
nocto 挂载选项
如果满足以下所有条件
- 您在客户端上挂载的导出仅供一个客户端使用。
- 在一个客户端上写入的文件是否不会立即出现在其他客户端上并不太重要。
- 在客户端写入文件后,客户端认为该文件已保存,然后客户端崩溃,文件可能会丢失,这并不重要。
使用 nocto 挂载选项,这将禁用关闭时打开行为。
async 导出选项
您的状况是否符合这些条件?
- 重要的是,当在一个客户端上写入后关闭文件时,它是
- 立即在所有其他客户端上可见。
- 即使客户端在关闭文件后立即崩溃,也安全地存储在服务器上。
- 如果服务器崩溃,对您来说不重要的是
- 您可能会丢失客户端最近写入的文件。
- 当服务器重新启动时,客户端会认为其最近的文件存在,即使实际上它们已丢失。
在这种情况下,您可以对这些特定导出在服务器的 /etc/exports
文件中使用 async
而不是 sync
。有关详细信息,请参阅 exports 手册页。在这种情况下,在客户端上使用 nocto
挂载选项没有意义。
缓冲区缓存大小和 MTU
症状: 高内核或 IRQ CPU 使用率,通过网卡的非常高的数据包计数。
这是一个更棘手的优化。在花太多时间在这上面之前,请确保这确实是问题所在。默认值通常在大多数情况下都很好。
有关 NFS 中 I/O 缓冲的信息,请参阅 本文。本质上,数据在发送之前会累积到缓冲区中。缓冲区的大小将影响数据通过网络传输的方式。网络设备的最大传输单元 (MTU) 也会影响吞吐量,因为缓冲区在通过网络发送之前需要拆分为 MTU 大小的块。如果您的缓冲区大小太大,则内核或硬件可能会花费太多时间将其拆分为 MTU 大小的块。如果缓冲区大小太小,则发送大量小数据包会产生开销。您可以使用客户端上的 rsize 和 wsize 挂载选项来更改缓冲区缓存大小。为了获得最佳吞吐量,您需要进行实验并找到适合您设置的最佳值。
可以更改许多网卡的 MTU。如果您的客户端在单独的子网(例如,用于 Beowulf 集群),则可以安全地将所有网卡配置为使用高 MTU。这应该在超高带宽环境中使用。
有关更多信息,请参阅 NFS#性能调优。
调试
使用 rpcdebug
使用 rpcdebug
是操纵内核接口的最简单方法,可以代替将位掩码回显到 /proc。
选项 | 描述 |
---|---|
-c | 清除给定的调试标志 |
-s | 设置给定的调试标志 |
-m 模块 | 指定要设置或清除哪个模块的标志。 |
-v | 增加 rpcdebug 输出的详细程度 |
-h | 打印帮助消息并退出。与 -v 选项结合使用时,还会打印可用的调试标志。 |
对于 -m 选项,可用的模块是
模块 | 描述 |
---|---|
nfsd | NFS 服务器 |
nfs | NFS 客户端 |
nlm | 网络锁管理器,在 NFS 客户端或服务器中 |
rpc | 远程过程调用模块,在 NFS 客户端或服务器中 |
示例
rpcdebug -m rpc -s all # sets all debug flags for RPC rpcdebug -m rpc -c all # clears all debug flags for RPC rpcdebug -m nfsd -s all # sets all debug flags for NFS Server rpcdebug -m nfsd -c all # clears all debug flags for NFS Server
设置标志后,您可以 tail 日志以获取调试输出,通常以 root 身份运行 journalctl -fl
或类似命令。
使用 mountstats
nfs-utils 软件包包含 mountstats
工具,该工具可以检索有关 NFS 挂载的大量统计信息,包括平均时间和数据包大小。
$ mountstats Stats for example:/tank mounted on /tank: NFS mount options: rw,sync,vers=4.2,rsize=524288,wsize=524288,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,soft,proto=tcp,port=0,timeo=15,retrans=2,sec=sys,clientaddr=xx.yy.zz.tt,local_lock=none NFS server capabilities: caps=0xfbffdf,wtmult=512,dtsize=32768,bsize=0,namlen=255 NFSv4 capability flags: bm0=0xfdffbfff,bm1=0x40f9be3e,bm2=0x803,acl=0x3,sessions,pnfs=notconfigured NFS security flavor: 1 pseudoflavor: 0 NFS byte counts: applications read 248542089 bytes via read(2) applications wrote 0 bytes via write(2) applications read 0 bytes via O_DIRECT read(2) applications wrote 0 bytes via O_DIRECT write(2) client read 171375125 bytes via NFS READ client wrote 0 bytes via NFS WRITE RPC statistics: 699 RPC requests sent, 699 RPC replies received (0 XIDs not found) average backlog queue length: 0 READ: 338 ops (48%) avg bytes sent per op: 216 avg bytes received per op: 507131 backlog wait: 0.005917 RTT: 548.736686 total execute time: 548.775148 (milliseconds) GETATTR: 115 ops (16%) avg bytes sent per op: 199 avg bytes received per op: 240 backlog wait: 0.008696 RTT: 15.756522 total execute time: 15.843478 (milliseconds) ACCESS: 93 ops (13%) avg bytes sent per op: 203 avg bytes received per op: 168 backlog wait: 0.010753 RTT: 2.967742 total execute time: 3.032258 (milliseconds) LOOKUP: 32 ops (4%) avg bytes sent per op: 220 avg bytes received per op: 274 backlog wait: 0.000000 RTT: 3.906250 total execute time: 3.968750 (milliseconds) OPEN_NOATTR: 25 ops (3%) avg bytes sent per op: 268 avg bytes received per op: 350 backlog wait: 0.000000 RTT: 2.320000 total execute time: 2.360000 (milliseconds) CLOSE: 24 ops (3%) avg bytes sent per op: 224 avg bytes received per op: 176 backlog wait: 0.000000 RTT: 30.250000 total execute time: 30.291667 (milliseconds) DELEGRETURN: 23 ops (3%) avg bytes sent per op: 220 avg bytes received per op: 160 backlog wait: 0.000000 RTT: 6.782609 total execute time: 6.826087 (milliseconds) READDIR: 4 ops (0%) avg bytes sent per op: 224 avg bytes received per op: 14372 backlog wait: 0.000000 RTT: 198.000000 total execute time: 198.250000 (milliseconds) SERVER_CAPS: 2 ops (0%) avg bytes sent per op: 172 avg bytes received per op: 164 backlog wait: 0.000000 RTT: 1.500000 total execute time: 1.500000 (milliseconds) FSINFO: 1 ops (0%) avg bytes sent per op: 172 avg bytes received per op: 164 backlog wait: 0.000000 RTT: 2.000000 total execute time: 2.000000 (milliseconds) PATHCONF: 1 ops (0%) avg bytes sent per op: 164 avg bytes received per op: 116 backlog wait: 0.000000 RTT: 1.000000 total execute time: 1.000000 (milliseconds)
内核接口
调试标志的位掩码可以回显到接口以启用输出到 syslog;0 是默认值
/proc/sys/sunrpc/nfsd_debug /proc/sys/sunrpc/nfs_debug /proc/sys/sunrpc/nlm_debug /proc/sys/sunrpc/rpc_debug
为这些接口注册了 Sysctl 控件,因此可以代替 echo 使用它们
sysctl -w sunrpc.rpc_debug=1023 sysctl -w sunrpc.rpc_debug=0 sysctl -w sunrpc.nfsd_debug=1023 sysctl -w sunrpc.nfsd_debug=0
在运行时,服务器会保存可以检查的信息
grep . /proc/net/rpc/*/content cat /proc/fs/nfs/exports cat /proc/net/rpc/nfsd ls -l /proc/fs/nfsd
/proc/net/rpc/nfsd
的详细信息(用户空间工具 nfsstat
以漂亮的格式打印此信息)
* rc (reply cache): <hits> <misses> <nocache>
- hits: client it's retransmitting
- misses: a operation that requires caching
- nocache: a operation that no requires caching
* fh (filehandle): <stale> <total-lookups> <anonlookups> <dir-not-in-cache> <nodir-not-in-cache>
- stale: file handle errors
- total-lookups, anonlookups, dir-not-in-cache, nodir-not-in-cache
. always seem to be zeros
* io (input/output): <bytes-read> <bytes-written>
- bytes-read: bytes read directly from disk
- bytes-written: bytes written to disk
* th (threads): <threads> <fullcnt> <10%-20%> <20%-30%> ... <90%-100%> <100%>
DEPRECATED: All fields after <threads> are hard-coded to 0
- threads: number of nfsd threads
- fullcnt: number of times that the last 10% of threads are busy
- 10%-20%, 20%-30% ... 90%-100%: 10 numbers representing 10-20%, 20-30% to 100%
. Counts the number of times a given interval are busy
* ra (read-ahead): <cache-size> <10%> <20%> ... <100%> <not-found>
- cache-size: always the double of number threads
- 10%, 20% ... 100%: how deep it found what was looking for
- not-found: not found in the read-ahead cache
* net: <netcnt> <netudpcnt> <nettcpcnt> <nettcpconn>
- netcnt: counts every read
- netudpcnt: counts every UDP packet it receives
- nettcpcnt: counts every time it receives data from a TCP connection
- nettcpconn: count every TCP connection it receives
* rpc: <rpccnt> <rpcbadfmt+rpcbadauth+rpcbadclnt> <rpcbadfmt> <rpcbadauth> <rpcbadclnt>
- rpccnt: counts all rpc operations
- rpcbadfmt: counts if while processing a RPC it encounters the following errors:
. err_bad_dir, err_bad_rpc, err_bad_prog, err_bad_vers, err_bad_proc, err_bad
- rpcbadauth: bad authentication
. does not count if you try to mount from a machine that it's not in your exports file
- rpcbadclnt: unused
* procN (N = vers): <vs_nproc> <null> <getattr> <setattr> <lookup> <access> <readlink> <read> <write> <create> <mkdir> <symlink> <mknod> <remove> <rmdir> <rename> <link> <readdir> <readdirplus> <fsstat> <fsinfo> <pathconf> <commit>
- vs_nproc: number of procedures for NFS version
. v2: nfsproc.c, 18
. v3: nfs3proc.c, 22
- v4, nfs4proc.c, 2
- statistics: generated from NFS operations at runtime
* proc4ops: <ops> <x..y>
- ops: the definition of LAST_NFS4_OP, OP_RELEASE_LOCKOWNER = 39, plus 1 (so 40); defined in nfs4.h
- x..y: the array of nfs_opcount up to LAST_NFS4_OP (nfsdstats.nfs4_opcount[i])
NFSD 调试标志
/usr/include/linux/nfsd/debug.h
/* * knfsd debug flags */ #define NFSDDBG_SOCK 0x0001 #define NFSDDBG_FH 0x0002 #define NFSDDBG_EXPORT 0x0004 #define NFSDDBG_SVC 0x0008 #define NFSDDBG_PROC 0x0010 #define NFSDDBG_FILEOP 0x0020 #define NFSDDBG_AUTH 0x0040 #define NFSDDBG_REPCACHE 0x0080 #define NFSDDBG_XDR 0x0100 #define NFSDDBG_LOCKD 0x0200 #define NFSDDBG_ALL 0x7FFF #define NFSDDBG_NOCHANGE 0xFFFF
NFS 调试标志
/usr/include/linux/nfs_fs.h
/* * NFS debug flags */ #define NFSDBG_VFS 0x0001 #define NFSDBG_DIRCACHE 0x0002 #define NFSDBG_LOOKUPCACHE 0x0004 #define NFSDBG_PAGECACHE 0x0008 #define NFSDBG_PROC 0x0010 #define NFSDBG_XDR 0x0020 #define NFSDBG_FILE 0x0040 #define NFSDBG_ROOT 0x0080 #define NFSDBG_CALLBACK 0x0100 #define NFSDBG_CLIENT 0x0200 #define NFSDBG_MOUNT 0x0400 #define NFSDBG_FSCACHE 0x0800 #define NFSDBG_PNFS 0x1000 #define NFSDBG_PNFS_LD 0x2000 #define NFSDBG_STATE 0x4000 #define NFSDBG_ALL 0xFFFF
NLM 调试标志
/usr/include/linux/lockd/debug.h
/* * Debug flags */ #define NLMDBG_SVC 0x0001 #define NLMDBG_CLIENT 0x0002 #define NLMDBG_CLNTLOCK 0x0004 #define NLMDBG_SVCLOCK 0x0008 #define NLMDBG_MONITOR 0x0010 #define NLMDBG_CLNTSUBS 0x0020 #define NLMDBG_SVCSUBS 0x0040 #define NLMDBG_HOSTCACHE 0x0080 #define NLMDBG_XDR 0x0100 #define NLMDBG_ALL 0x7fff
RPC 调试标志
/usr/include/linux/sunrpc/debug.h
/* * RPC debug facilities */ #define RPCDBG_XPRT 0x0001 #define RPCDBG_CALL 0x0002 #define RPCDBG_DEBUG 0x0004 #define RPCDBG_NFS 0x0008 #define RPCDBG_AUTH 0x0010 #define RPCDBG_BIND 0x0020 #define RPCDBG_SCHED 0x0040 #define RPCDBG_TRANS 0x0080 #define RPCDBG_SVCXPRT 0x0100 #define RPCDBG_SVCDSP 0x0200 #define RPCDBG_MISC 0x0400 #define RPCDBG_CACHE 0x0800 #define RPCDBG_ALL 0x7fff