NFS/故障排除

来自 ArchWiki
< NFS

本文或章节已过时。

原因: 并非所有章节都根据 NFSv4 的更改进行了更新。(在Talk:NFS/Troubleshooting中讨论)

常见问题和解决方案的专用文章。

服务器端问题

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 身份写入文件时出现 “Permission denied”

  • 如果您需要以 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: Program not registered”

确保服务器站点上的 nfs-server.servicerpcbind.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-networkdNetworkManager 的用户可能会注意到 NFS 挂载在启动时未挂载。

通过启用 systemd-networkd-wait-online.serviceNetworkManager-wait-online.service 来强制网络完全配置。这可能会减慢启动过程,因为并行运行的服务会减少。

提示: 如果 NFS 服务器仅期望 IPV4 地址,并且您正在使用 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 服务器上出现一些问题。如果您遇到性能缓慢、频繁断开连接以及国际字符问题,请通过在 Mac 客户端上的 /etc/nfs.conf 中添加行 nfs.client.mount.options = intr,locallocks,nfc 来编辑默认挂载选项。有关挂载选项的更多信息,请参见 OS X mount_nfs(8)

复制大文件时客户端间歇性冻结

如果您从客户端计算机复制大文件到 NFS 服务器,传输速度非常快,但几秒钟后速度下降,并且您的客户端计算机间歇性完全锁定一段时间,直到传输完成。

尝试在客户端上添加 sync 作为挂载选项(例如在 /etc/fstab 中)以解决此问题。

mount.nfs: Operation not permitted

NFSv4

如果您使用 Kerberos (sec=krb5*),请确保客户端和服务器时钟正确。建议使用 ntpdsystemd-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: Protocol not supported

当您在 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 挂载选项

警告: Linux 内核似乎没有正确地遵守此选项。文件在关闭时仍然会被刷新。

如果满足以下所有条件

  • 您在客户端上挂载的导出项仅供一个客户端使用。
  • 在一个客户端上写入的文件是否不会立即出现在其他客户端上并不重要。
  • 客户端写入文件后,客户端认为文件已保存,然后客户端崩溃,文件可能会丢失,这并不重要。

使用 nocto 挂载选项,这将禁用关闭到打开行为。

async 导出选项

您的情景是否符合以下条件?

  • 重要的是,在一个客户端上写入后关闭文件时,它必须
    • 立即在所有其他客户端上可见。
    • 即使客户端在关闭文件后立即崩溃,也安全地存储在服务器上。
  • 服务器崩溃时,对您来说并不重要
    • 您可能会丢失客户端最近写入的文件。
    • 当服务器重新启动时,客户端会认为它们最近的文件存在,即使它们实际上已丢失。

在这种情况下,您可以为这些特定导出项在服务器的 /etc/exports 文件中使用 async 而不是 sync。有关详细信息,请参阅 exports 手册页。在这种情况下,在客户端上使用 nocto 挂载选项是没有意义的。

缓冲区缓存大小和 MTU

症状: 高内核或 IRQ CPU 使用率,通过网卡的数据包计数非常高。

这是一个更棘手的优化。在花费太多时间之前,请确保这确实是问题所在。默认值通常在大多数情况下都很好。

有关 NFS 中 I/O 缓冲的信息,请参阅这篇文章。本质上,数据在发送之前会累积到缓冲区中。缓冲区的大小将影响数据在网络上的传输方式。网络设备的最大传输单元 (MTU) 也会影响吞吐量,因为缓冲区需要拆分为 MTU 大小的块,然后才能通过网络发送。如果您的缓冲区大小太大,内核或硬件可能会花费太多时间将其拆分为 MTU 大小的块。如果缓冲区大小太小,则发送大量小数据包会产生开销。您可以使用客户端上的 rsizewsize 挂载选项来更改缓冲区缓存大小。为了获得最佳吞吐量,您需要进行实验并找到适合您设置的最佳值。

可以更改许多网卡的 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

设置标志后,您可以跟踪日志以获取调试输出,通常以 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

参见