linux环境下嵌入式产品的NFS应用

本文是作者在使用NFS过程中出现了一些问题,经过查询资料、翻译以及自己跟踪代码,写下本片博文。NFS V3和NFS V4都有说明,如果首次使用,建议直接NFS V4。由于作者知识有限,如果有错误或者未提及的地方,请见谅!

第1章 NFS功能介绍 介绍了NFS的定义、优缺点、nfs-utils-1.3.4新增特性以及主要工作原理 第2章 NFS源码包介绍 介绍了源码包的组成、获取、构建 第3章 组件介绍 介绍相关命令的作用和语法 第4章 NFS应用 介绍NFS文件系统的部署和使用 第5章 F&Q 记录使用时出现的问题

1、NFS功能介绍

1.1、 定义:

NFS(Network File System)网络文件系统,是分布式计算机系统的一个组成部分,可实现在异构网络上共享和装配文件系统。最早由SUN公司开发,目前已成为文件服务的一种标准(RFC1904 RFC1813)。其最大的功能是可以通过网络,让不同操作系统的计算机可以共享数据,所以也可以看作是一个文件服务器。NFS除了SAMBA之外windows与linux及unix与linux之间通信的方法。NFS只是一种文件系统,本身没有传输功能,是基于RPC服务实现的,才能达到两个linux系统之间的文件目录共享。NFS采用C/S模型,提供资源的一端充当服务器,消费资源的一端充当客户端。
在linux系统中,NFS服务端和客户端都需要内核的支持,还需要有用户态程序进行配置和管理。nfs-utils就是用户态NFS配置管理工具包,它提供了一系列服务端和客户端的配置和管理。

1.2、优点:

  • 节省本地存储空间,对于大家都经常用到的资源,可以保存到NFS服务器上,大家通过网络去访问,不需要再本地留一份拷贝;
  • 节省移动介质设备数量,有了NFS,不需要用移动介质拷贝,只需要将移动设备上的资源放到一些软盘,光盘等这些介质上,从而有效减少移动介质数量;

1.3、缺点:

  • NFS在高并发场景和大存储下不适合,需要使用分布式存储MFS、FastDFS、TFS等;
  • 客户端的数据都是明文传输,并且没有用户认证机制,安全性一般,所以建议一般在局域网中使用;
  • 容易发生单点故障,即server服务宕机所有的客户端都不能访问;

1.4、nfs-utils-1.3.4新增特性

nfs-utils-1.3.4是最新的NFS版本,支持NFS V4。稳定版nfs-utils-1.3.4-2.1,测试版nfs-utils-1.3.4-2.4。由IETF RFC3530描述,基于NFS V2和NFS V3版本,增加了一些新的特性,并且随着版本更新对NFS V4的支持在不断完善。
NFS V4的目标是建立一个快速故障恢复、传输协议独立、操作系统和文件系统独立、简单和分布式文件系统,它有如下新特性:

  • 增强的安全特性。支持RPCSEC-GSS和使用身份映射访问远程域。NFS V3的安全性一直是大家诟病的地方,虽然在大量使用,但其安全隐患常常让使用他的人心存顾虑。NFS V4在这方面做了增强,可以通过配置来使用RPCSEC-GSS方式的身份认证,从而提高协议的安全性。另外,NFS V4还提供了Kerberos 5的安全机制。
  • 文件加锁功能改为在NFS核心协议中实现。rpc.lockd、rpc.mountd、rpc.statd将不在NFS V4中使用(但是仍然存在于linux 操作系统中,以支持NFS V2和NFS V3),这种实现也将使NFS 服务器配置防火墙更加简单。
  • NFS V4只支持TCP协议,UDP不在NFS V4中支持。
  • NFS V4支持ACL功能。
  • 原子操作的加强。NFS 客户端和服务器是通过RPC服务来进行的,NFS V4支持复合的RPC请求,即一个RPC请求可以携带多个操作,这样,NFS 客户端可以通过一次RPC请求操作完成查找、打开、读/写等。这些操作没有逻辑上的与、或关系,而是由服务端按顺序处理,如果其中一个操作失败,整个RPC请求就返回,使操作的原子性加强。
  • 状态机制的引入。NFS V4中客户端对文件操作时,在文件锁中增加了一种状态。这个状态基于时间租用机制。NFS服务器为客户端指定了租赁周期,如果客户端在指定时间内没有更新自己的状态,则服务器会释放这个客户端的所有状态,并默认客户端不可达。在客户端对文件操作时,服务端也会赋予一个状态编号,表明文件正在被哪个客户端进行哪种操作。
  • 委派。NFS V3中,客户端通常当做它们已经打开的文件之间存在竞争。客户端通过频繁的向服务端发送请求来查找该文件是否被其他人修改,系统保持了较弱的一致性,这会造成比较高的网络流程并产生一定的延迟。在客户端操作文件时,所有写I/O必须同步,这样会影响客户端性能。

但是在NFS V4中,允许服务端的文件委派给客户端,以便实现更加积极的客户端数据缓存并允许缓存锁定状态。服务器通过委派来放弃对文件的更新和客户端的锁定状态的控制。通过允许客户端在本地进行不同的操作和数据缓存,减少了延迟。目前有读和写两种委派。服务端在存在文件竞争时可以从客户端调回委派。一旦客户端具有委派,它就能在本地缓存数据上进行操作,以避免网络延时并优化I/O。

1.5、工作原理之RPC

NFS支持的功能非常多,而不同的功能都会使用不同的端口来启动,所以我们先介绍下NFS中最重要的一个服务框架—远程过程调用(Remote Procedure Call):
NFS每启动一个功能都会启用一些端口来传输数据,因此NFS这么多功能所用的端口才没有固定,而是采用随机一些小于724的端口来作为传输之用,但如此以来又造成了客户端访问服务器的困扰,因为客户端需要知道服务器的相关端口才能够联机,当NFS的进程启动时都会向RPC注册自己的服务端口,PID以及所监听的IP等信息,所以RPC就知道每个服务与对应的端口等信息,而RPC本身则使用111端口作为监听客户端的请求并回报客户端正确的端口。也就是因为这样,启动NFS服务进程之前,必须要先启动RPC服务,否则NFS无法向RPC注册。另外,重新启动RPC时原本注册的信息会不见,因此RPC重新启动后它管理的所有服务都需要重新启动完成RPC注册。
所谓的Remote Procedure Call,就是在本地调用远程主机上的Procedure,比如在本地cat 命令时,会发起某些系统调用如open,read,close等,并将cat的选项和参数传递给这些函数,于是最终实现了文件的查看功能。在RPC层面理解,上面发起的系统调用就是Procedure,每个Procedure对应上面一个或多个功能

2、NFS源码包介绍

2.1、NFS功能代码分四个部分,nfs-common、rpcbind、nfs-kernel、其他与nfs-utils有关的软件包

  • nfs-common:支持nfs用户态server以及client,也就是常见的nfs-utils以及rpcbind源码包,这个包包含lockd, statd, showmount, nfsstat, and mount.nfs.;
  • rpcbind:旧版本为portmap,提供RPC通讯服务;
  • nfs-kernel-server:NFS内核服务器目前是Linux使用的推荐NFS服务器,具有NFSv3和NFSv4、通过GSS支持Kerberos等功能。它也比用户空间nfs服务器快得多,通常也更可靠。然而,调试比用户空间服务器更困难,并且具有稍微不同的功能集。这个包包含使用NFS内核服务器所需的用户空间支持,包括/usr/sbin/exportfs、/usr/sbin/rpc.mountd、

/usr/sbin/rpc.nfsd组件;

  • 其他与nfs-utils有关的软件包:编译时候会提示出来,构建架构特定包依赖和构建架构特色包依赖;

2.2、源码获取

nfs-common、nfs-kernel-server可以从这获取,支持多种硬件架构https://packages.qa.debian.org/n/nfs-utils.html
rpcbind,支持多种硬件架构:https://packages.debian.org/jessie/rpcbind
其他与nfs-utils有关的软件包:编译提示缺少什么,就下载对应包

2.3、构建过程

每个下载的包,都有个README文档,会告诉你如何编译;各种守护进程,因为大多数分发版都用他们自己的守护进程替换,所以打包的任何脚本都不会得到太多测试。相反,会解释启动中涉及的依赖关系,以便可以编写脚本以正确工作。

3、NFS组件介绍

NFS服务端组件主要有:
1、rpcbind:主要讲RPC协议的程序号转换为DAPRA协议的端口号;
2、rpc.mountd:使得NFS服务端的mount协议生效,远程可以通过mount命令访问服务器;
3、exportfs:导出NFS共享目录,客户端可以通过NFS服务访问服务器的这些共享目录;
4、rpc.nfsd:NFS服务的用户态程序;
5、sm-notify:如果服务器和客户端的重启,向其他NFS终端发送该终端重启的通知,主要应用于NFS V3协议,NFS V4协议中该功能由内核来完成;
6、rpc.statd:监听来自其他主机的重启通知,与sm-notify配套使用,主要应用与NFS V3协议,NFS V4协议中该功能由内核来完成;
7、showmount:显示服务器端mount相关的配置信息;

NFS客户端组件主要有:
1、rpcbind:主要讲RPC协议的程序号转换为DAPRA协议的端口号;
2、sm-notify:如果服务器和客户端的重启,向其他NFS终端发送该终端重启的通知,主要应用于NFS V3协议,NFS V4协议中该功能由内核来完成;
3、rpc.statd:监听来自其他主机的重启通知,与sm-notify配套使用,主要应用与NFS V3协议,NFS V4协议中该功能由内核来完成;
4、mount.nfs:按NFS V3协议挂载网络共享目录;
5、mount.nfs4:按NFS V4协议挂载网络共享目录;
6、umount:卸载网络共享目录;

3.1、rpcbind

rpcbind主要完成RPC程序号到DARPA协议端口号的一种转换,在服务端和客户端都必须被首先启动。

语法

rpcbind[-V][-d][-f][-F][-t dir][-m file][-u uid][-g gid][-v][-i address][-l][-p port][-U username]

参数说明

-V 查询版本号 -d rpcbind进程按照调试模式启动 -f 通过标准错误输出打印日志信息 -F 按照普通形式打印日志信息 -t dir

-m file 指定maping file文件 -u uid 指定用户ID -g gid 指定用户组ID -U uasername 按照用户名启动rpcbind -i address 绑定rpcbind到指定的ip地址 -v 按照verbose模式启动 -l 绑定rpcbind到环回地址127.0.0.1 -p port 绑定rpcbind的端口号

3.2、exportfs

描述

exportfs进程根据文件/etc/exports的内容导出一张文件系统表,这张表中说明了本地文件系统中允许被NFS客户端访问的文件目录。导出的信息保存在/var/lib/nfs/etab文件中,供rpc.mountd进程使用。

语法

exportfs [-a][-i][-r][-u][-f][-v]

参数说明

-a 导出或者不导出全部目录 -i 忽略/etc/exports文件中的参数设置,按默认情况导出NFS服务的共享目录的参数 -r 重新导出NFS的所有共享,目录,将/var/lib/nfs/etab中的信息同步到/etc/exports -u 关闭一个或者多个NFS服务的共享目录 -f NFS启动时会将内核中的导出表的信息清除,该参数能让rpc.mountd进程更新以前内核导出表中有效的客户端入口 -v 按照verbose模式运行,即显示全部信息

3.3、rpc.mountd

描述

rpc.mountd守护进程主要支持服务端的NFS mount协议,当接收一个客户端的mount请求后,如果客户端允许它将向/var/lib/nfs/rmtab中添加一条客户端信息(包括客户端ip和mount的服务器目录两部分);当接收到客户端的umount请求后,它将删除文件/var/lib/nfs/rmtab中相应的信息。

语法

rpc.mountd [-d kind or -debug kind][-F or --foregroud][-f or --exports-file][-h or --help][-o num or --descriptors num][-N or —no-nfs-version][-n or --no-tcp][-P][-p or --port num][-s or --state-directory-path directory][-t N or --num-threads=N][-V or --nfs-version][-v or --version]

参数说明

-d kind or -debug kind 开启调试模式。Kind的值为all,auth,call,general and parse -F or --foregroud 前台运行 -f or --exports-filed 指定客户端mount的导出文件 -h or --help 帮助命令 -o num or --descriptors num 开启对文件描述符的限制 -N or --no-nfs-version NFS版本支持说明。如果内核编译时提示未提供NFS V4功能,请在参数中输入 -n or --no-tcp 指定NFS不支持TCP协议 –p or --port num 用于指定RPC的端口号 -s or --state-directory-path directory 指定存放statd状态信息的路径 -t N or --num-threads=N 指定rpc.mountd启动锁需要的线程数,默认情况下为1 -V or --nfs-version 指定rpc.mountd的NFS协议 -v or --version 打印rpc.mountd的版本号

3.4、rpc.nfsd

描述

rpc.nfsd是NFS服务的用户态进程,nfsd的主要功能还是由内核的nfsd完成的。动作包括对文件或者目录的详细操作:open、read、close、remove、getattr等。rpc.nfsd仅能修改内核服务的socket类型,NFS版本以及nfsd内核模块使用的线程数。

语法

rpc.nfsd [-d or --debug][-H or --host hostname][-p or --port port][-N or --no-nfs-version][-s or --syslog][-T or --no-tcp][-U or --no-udp]

参数说明

-d or --debug 开启调试模式记录调试信息 -H or --host hostname 指定NFS访问的主机名或者IP地址 -p or --port por 指定侦听NFS请求的端口号 -N or --no-nfs-version NFS版本支持说明。如果内核编译时提示未提供NFS V4功能,请在参数中输入 -s or --syslog 指定通过系统日志来记录错误信息 -T or --no-tcp 关闭NFS的TCP链接,使客户端通过TCP协议访问失效 -U or --no-udp 关闭NFS的UDP链接,使客户端通过UDP协议访问失效

3.5、sm-notify

描述

在linux系统中,文件锁不属于文件的持续状态,当主机重新启动后该状态会消失。当文件锁状态由于远端主机重启而消失时,NFS系统同样也需要侦听到。对于NFS V2和V3来说,Network Status Monitor(以下简称NSM)就是通知NFS文件系统上的其他主机本地主机发生了重启。NSM主要包括两个部分:sm-notify和rpc.statd。
sm-notify:主要负责向NFS文件系统上的其他主机通知本地主机已经重启的通知。
rpc.statd:一个负责侦听其他主机重启的守护进程;并且管理一张主机列表,该列表告诉sm-notify当主机重启时需要向那些远程主机发送通知消息。
当客户端重启后,服务端必须释放所有被客户端使用的文件锁;当服务端重启后,客户端必须使服务端重新启用为客户端使用的文件锁。该组件主要在NFS V2和NFS V3中启用,NFS V4这部分功能由内核完成。

语法

sm-notify [-d][-f][-m retry-time][-n][-P,–state-directory-path pathname][-p port][-v ipaddr|hostname]

参数说明

-d 保持sm-notify与控制终端的链接并运行在前台,确保进程能被检测到 -f 即使重启后sm-notify已经运行,仍然发送主机重启的通知消息 -m retry-time 设置重复发送时间。如果接收发没有回应,在该时间内重复发送。默认情况下为15分钟,如果设置为0表示不停的发送,直到该进程被强制关闭 -n 禁止sm-notify去更新本地NSM的状态 -p port 指定sm-notify发送重启信息的端口 -P,–state-directory-path pathname 指定NSM状态消息的存放路径 -v ipaddr hostname

3.6、rpc.statd

描述

在linux系统中,文件锁不属于文件的持续状态,当主机重新启动后该状态会消失。当文件锁状态由于远端主机重启而消失时,NFS系统同样也需要侦听到。对于NFS V2和V3来说,Network Status Monitor(以下简称NSM)就是通知NFS文件系统上的其他主机本地主机发生了重启。NSM主要包括两个部分:sm-notify和rpc.statd。
sm-notify:主要负责向NFS文件系统上的其他主机通知本地主机已经重启的通知。
rpc.statd:一个负责侦听其他主机重启的守护进程;并且管理一张主机列表,该列表告诉sm-notify当主机重启时需要向那些远程主机发送通知消息。
当客户端重启后,服务端必须释放所有被客户端使用的文件锁;当服务端重启后,客户端必须使服务端重新启用为客户端使用的文件锁。该组件主要在NFS V2和NFS V3中启用,NFS V4这部分功能由内核完成。

语法

rpc.statd [-d,–no-syslog][-F,–foreground][-h,-?,–help][-H,–ha-callout prog][-L,–no-notify][-p,–port port][-n,–name ipaddr | hostname][-P,–state-directory-path pathname][-o,–outgoing-port port][-v,-V,–version]

参数说明

-d,–no-syslog 使得rpc.statd通过标准错误输入日志信息,默认情况为通过系统日志打印日志信息 -F,–foreground 保持该进程在前台运行,确保NSM状态能够被监听到 -h,-?,–help 显示帮助信息 -L,–no-notify 阻止rpc.statd启动时自动启动sm-notify -N 告知rpc.statd去启动sm-notify -P,–state-directory-path pathname 指定NSM状态消息的存放路径 -o,–outgoing-port port 指定sm-notify发送重启消息的端口号 -n,–name ipaddr hostname -v,-V,–version 指定rpc.statd的版本号

3.7、showmount

描述

显示服务器断与Mount的相关配置信息,比如用于mount的共享目录,mount的相关消息记录。

语法

showmount [-a][-d or --directories][-e or --exports][-h or --help][-v or --version]

参数说明

-a 显示所有的mount信息,包括客户端ip和mount的根目录 -d or --directories 只显示Mount的根目录 -e or --exports 显示服务器端的共享文件目录列表 -h or --help 显示帮助信息 -v or --version 显示版本信息

3.8、mount.nfs

描述

按照NFS V3协议挂在网络共享目录。

语法

mount.nfs [-r][-v][-V][-w][-f][-n][-h][-o options] device dir

参数说明

-r 以只读权限mount共享目录,等于 -o ro -v 显示所有信息 -V 显示版本信息 -w 以读写权限mount共享目录,等于 -o rw -f 假mount,并不是真正的挂载NFS文件系统 -n mount后,不能修改/etc/mtab -o 参数比较多,可以同时使用多个,之间用英文","间隔开,用于指定mount启动时的属性,见下面分析 -h 显示帮助信息

mount [-fnrsvw] [-t vfstype] [-o options] device dir
mount.nfs相当于mount -t nfs,
-t:指定档案系统的型态,通常不必指定。mount 会自动选择正确的型态。
-o rsize=n:在NFS服务器读取文件时NFS使用的字节数,默认值是4096个字节。
-o wsize=n:向NFS服务器写文件时NFS使用的字节数,默认值是4096个字节。
-o timeo=n:从超时后到第1次重新传送占用的1/7秒的数目,默认值是7/7秒。
-o retry=n:在放弃后台mount操作之前可以尝试的次数,默认值是7 000次。
-o soft:使用软挂载的方式挂载系统,若Client的请求得不到回应,则重新请求并传回错误信息。
-o hard:使用硬挂载的方式挂载系统,该值是默认值,重复请求直到NFS服务器回应。
-o intr:允许NFS中断文件操作和向调用它的程序返回值,默认不允许文件操作被中断。
-o fg:一直在提示符下执行重复挂载。
-o bg:如果第1次挂载文件系统失败,继续在后台尝试执行挂载,默认值是失败后不在后台处理。
-o tcp:对文件系统的挂载使用TCP,而不是默认的UDP。

soft和hard模式
当nfs的服务器端出现异常的时候,linux服务器的底层有重发机制,nfs客户端一直去向服务器端请求,判断服务器是否正常,一直阻塞。
当客户端挂载的时候采用hard模式,服务器端出现异常,则客户端会一直发请求,直到服务器正常。
当客户端挂载的时候采用soft模式,我们可以配置timeo和retry参数,配置超时时间,服务器端出现异常,客户端也会向服务器端发请求,当超过我们配置的时间,则会返回错误,不会一直阻塞。
hard模式挂载:
mount -t nfs -o rw 192.168.1.2:/home/nfs /mnt local_path
soft模式挂载
mount -t nfs -o rw,soft,timeo=30,retry=3 192.168.1.2:/home/nfs /mnt local_path
timeo的单位是0.1秒,配置为30就是隔3秒客户端向服务器端请求。

3.9、mount.nfs4

描述

按照NFS V4协议挂在网络共享目录,其语法与参数说明与mount.nfs完全一致

3.10、umount

描述

卸载NFS文件系统

语法

umount [-f][-v][-n][-r][-l][-h]

参数说明

-f 强制执行umount -v 显示所有信息 -n umount后,不能修改文件/etc/mtab -r 如果umount失败,以只读权限重新mount -l –l 并不是马上umount,而是在该目录空闲后再移除目录的所有引用 -h 显示帮助信息

有时候我们经常遇到umount的时候提示device busy的提示,这是因为卸载的目录正在被占用,处理方法为:
fuser -m /xxx 可以查看到是谁占用的这个卸载目录,用于问题定位;再使用kill -9 PID杀掉刚才查看到的占用卸载目录的PID,当然也可以直接使用fuser -m -k /xxx

4、NFS的应用

4.1 内核支持

首先需要确定服务器和客户端的内核是否都支持NFS V3和NFS V4服务,如果不支持在内核中添加如下配置项

File system->Network File Systems->NFS file system support
File system->Network File Systems->Provide NFSv3 client support
File system->Network File Systems->Provide NFSv4 client support
File system->Network File Systems->NFS server support
File system->Network File Systems->Provide NFSv3 server support
File system->Network File Systems->Provide NFSv4 server support
File system->Network File Systems->Provide NFS server over TCP support
File system->Network File Systems->Provide RPCSEC_GSS authentication
File system->Network File Systems->Kerberos mechanism for RPCSEC_GSS
File system->Network File Systems->Provide NFSv4 ACL support

4.2 开启系统日志功能

由于nfs-utils的错误提示信息都是输出到系统日志中,所以服务端和客户端都需要开启日志记录功能,以便于查看nfs服务失败的原因。

  • 核查/var/log目录是否存在。如果不存在,需要手动创建,因为系统日志将会以messages为文件名保存在该目录下。需要root用户查看cat /var/log/messages
  • 启动记录日志的守护进程syslogd

4.3 服务端部署

  • 将output下的sbin目录下的文件拷贝到目标机的/usr/sbin目录下
  • 检查nfs-utils所需要的相关文件和目录,如果不存在,需要手动创建,其中etab xtab rmtab文件内容为空

目录文件:
/var/run
/var/lib/nfs/sm
/var/lib/nfs/sm.bak
/var/lib/nfs/v4recovery
文件:
/var/lib/nfs/etab
/var/lib/nfs/xtab
/var/lib/nfs/rmtab

  • 检查/etc/services内容

services文件需要包含两条nfs端口:
1、环境中该文件存在,只需要核查是否包含了nfs端口信息,如果没有则需要向文件中添加该信息;
2、环境中不存在该文件,手动创建并向其添加nfs端口信息
nfs端口信息如下:

nfs 2049/tcp nfsd
nfs 2049/udp nfsd

services文件的详细说明请参见4.3节问题分析

  • 挂在nfsd文件系统

mount -t nfsd /dev /proc/fs/nfsd

  • 发布共享目录

/etc/exports描述了NFS服务器对外共享的目录,一个可用的/etc/exports文件如下:

cat /etc/exports
/home/xx/test *(rw,fsid=0,no_subtree_check)

然后exportfs将文件发布出去

exportfs -arv

  • 启动rpcbind

/usr/sbin/rpcbind

  • 启动rpc.mountd

/usr/sbin/rpc.mountd

  • 启动rpc.statd -no-notify

/usr/sbin/rpc.statd -no-notify

  • 启动rpc.nfsd

/usr/sbin/rpc.nfsd

  • 启动sm-notify

/usr/sbin/sm-notify

与NFS V3不同的是NFS V4需要在输出目录的属性中增加一项fsid=0,否则,客户端在mount时会报错"reason given by server.No such file or directory"。
如果nfsd文件系统未能在exportfs、rpc.mountd等前挂在到/proc/fs/nfsd下,客户端在mount的时候会出现"mount.nfs4: Permission denied"或无响应了

4.4 客户端部署

  • 拷贝编译结果中的output/sbin目录下的文件到目标机的/usr/sbin目录下
  • 检查nfs-utils所需要的相关文件目录,如果目标机中没有下面的文件目录,需要手动创建

文件目录:
/var/run
/var/lib/nfs/sm
/var/lib/nfs/sm.bak

  • 检查文件/etc/hosts内容

hosts文件需要包含本地ip与主机名(可以通过hostname或者uname -n查看)之间的对应关系。例如:

192.168.0.10 xx

如果环境中不存在hosts文件,请手动创建,并添加本地ip与主机名的对应关系,关于本文件的详细说明请参见5.4节问题分析。

  • 启动rpcbind

/usr/sbin/rpcbind

  • 启动sm-notify

/usr/sbin/sm-notify

  • 启动rpc.statd

/usr/sbin/rpc.statd

sm-notify和rpc.statd的启动仅仅是在NFS V2和NFS V3上使用,如果使用NFS V4则不需要启动,V4版本这部分功能已经写到内核代码中支持了;
客户端进行NFS文件系统的远程登录时需要使用root权限。

4.5 客户端登录

  • 挂载NFS V4协议下的NFS文件系统

mount.nfs4 192.168.0.11:/ /home/xx/nfs

或者

mount -t nfs4 192.168.0.11:/ /home/xx/nfs

  • 挂载NFS V3协议下的NFS文件系统

mount.nfs 192.168.0.11:/xx /home/xx/nfs

或者

mount -t nfs 192.168.0.11:/xx /home/xx/nfs

  • 卸载NFS文件系统

umount /home/xx/nfs

与NFS V3不同的是NFS V4客户端mount的时候不需要输入全路径,只跟ip:/即可。如果输入全路径,反而会报错"reason given by server.No such file or directory"。

5、NFS常见问题

如果是在嵌入式设备上,我们可以使用dmesg查看内核日志,是否有错误打印,常见的网上都有解决方法,如果没有找到相关的解决方法,跟随错误打印去代码中定位吧。

5.1、通过NFS V4协议执行mount时报错,“reason given by server.No such file or directory”

  • 出现这个错误可能有两种情形:

/etc/exports文件导出目录中没有增加fsid=0参数;
mount命令参数使用不当,将服务端导出命令的全路径作为参数输入了,正确的做法应该是以"/"作为服务端;

5.2、客户端执行mount命令时出现"Permission denied"

出现这个错误可能有三种情形:

  • 客户端以非root用户执行mount(mount.nfs、mount.nfs4)命令;
  • nfsd文件系统未首先被挂载到/proc/fs/nfsd目录。重新启动nfs服务,在启动exportfs、rpc.mountd等命令前要先保证nfsd文件系统被挂载到/proc/fs/nfsd目录;
  • 检查服务端的nfs相关服务是否启动正常,尤其是rpcbind。

5.3、客户端执行mount命令时出现"svc:failed to register lockdv1 RPC service(errno 111)"错误

1问题原因:NFS mount默认选项包括文件锁,依赖于rpcbind提供的动态端口分配功能。 2 3解决办法:kill 文件锁(lockd)或者mount -o nolock参数启动 4 5

5.4、服务端或者客户端启动NFS的rpcbind组件没有起来

1问题原因:起不来的原因比较多,组件启动顺序错误、组件启动需要的配置没有或者错误、启动组件需要的端口未释放,处于TIME_WAIT状态。 2 3

请按照第4章的对照,对于端口TIME_WAIT导致的错误,可以使用ps -aux | grep 111查看是否该端口处于 TIME_WAIT状态。

1解决办法: 2非NAT环境下,修改/proc/sys/net/ipv4/tcp_tw_reuse=1 /proc/sys/net/ipv4/tcp_tw_recycle=0 /proc/sys/net/ipv4/tcp_fin_timeout=30 3 4

5.5、启动守护进程rpc.nfsd时出现"rpc.nfsd:unable to resolve ANYADDR:nfs to inet address:Servname not support for ai socktype;rpc.nfsd;unable to set any sockets for nfsd"

1问题原因:/etc/services文件不存在。 2 3

rpc.nfsd进程在运行时会调用c库函数getaddrinfo来获取服务器端的地址信息,其中NFS服务的端口号会从/etc/services中读取。/etc/services中保存了主机中所有网络服务的端口号,出现该问题的原因就是环境中缺少了/etc/services文件。所以进程无法通过nfs进程名查找到对应的端口号。

1解决办法:创建该文件,并在文件中添加: 2 3
  • nfs 2049/tcp nfsd
  • nfs 2049/udp nfsd

5.6、客户端执行mount.nfs4出现"can’t get address for XXXX",其中XXXX为通过hostname命令查看到的主机名。

1问题原因:/etc/hosts文件中缺少主机名与主机ip的对应关系,或者/etc/hosts为了不存。 2 3

mount.nfs4命令在启动时,首先调用c函数gethostbyname函数获取本地主机的ip地址所对应的ip信息,本地主机的ip地址信息会在mount.nfs4发送给服务端,服务端会将客户端的ip地址信息保存在文件中,作为客户端登录的记录。当客户端umount时,服务端删除相应的客户端ip信息。
而在/etc/hosts中保存了主机名,主机ip,主机域名的一一对应关系。gethostbyname就是通过主机名在文件中查找ip地址信息。由于环境中缺少了文件/etc/hosts或者缺少主机名与对应ip的对应关系,所以才会出现不能获取主机名对应的ip地址信息。

1解决办法:缺少/etc/hosts文件则创建或者存在直接添加本地主机名与之对应的ip信息,可以通过hostname或者uname -n命令查看主机名,比如tianlg;使用ifconfig查看本地主机网卡所使用的ip信息,比如:192.168.0.34,那么需要添加的信息如下: 2 3

192.168.0.34 tianlg

5.7、客户端mount服务器端共享目录成功后,在该目录下执行touch、rm、mkdir等命令失败,提示"Permission denied"。

1问题原因:客户端对共享目录的操作权限不足。 2 3

在NFS系统中,客户端是以其他群组的身份信息将服务端的共享目录挂载到本地的,因此,要使客户端对共享目录执行这些操作,服务端对外发布的共享目录必须是具有其他非本群组的写权限。例如:服务端发布的共享目录为/home/tianlg,增加该目录的其他非本群组的写权限的操作如下:

1解决办法:增加该共享目录的其他非本群组的写权限。 2 3

chmod o+w /home/tianlg

5.8、exportfs -arv提示/xxx does not support NFS export

  • 先检查内核, 包括内核版本(uname -a)以及内核配置(menuconfig)
  • 使用busybox的命令date查看系统时钟,对于NFS V3及以下版本当时间超过2038年1月19日时也会提示这种错误。

当NFS server在exportfs的时候需要依赖rpc服务,会向/proc/net/rpc/auth.unix.ip/channel写入命令行,在内核源码中分析,流程需要用到结构体cache_file_operations_procfs和ip_map_cache_template,函数调用流程如下:
cache_write_procfs()
cache_write()
cache_downcall()
cache_do_downcall()
cd->cache_parse()
ip_map_parse()
get_expiry()
cd->cache_parse回调ip_map_parse函数对应 /proc/net/rpc/auth.unix.ip/channel文件注册时的parse,最终在get_expiry()函数中因为时间戳太大,被误判为超时,这样NFS的RPC服务被清除,最终导致ip_map_parse()返回-22错误码。

代码交流 2021