NFS简介 网络文件系统(Network File System),通常我们都直接称呼其名为NFS,它可以在计算机间共享文件系统。NFS对用户几乎是透明的,并且是“无状态的”,这意味着当NFS服务器崩溃时不会丢失任何信息。客户机只是等着服务器恢复正常,然后就好像什么也没有发生过一样继续工作。
2 NFS服务器
RPC(NFS服务需要依赖RPC服务,这个比较重要)
要想了解NFS,必然要提到RPC这个服务。
因为NFS支持的功能还是比较多的,并且不同的功能都会使用不同的程序来启动。每启动一个功能就会启用一些端口来传输数据,因此NFS的功能所对应的端口才没有固定,而是采用随机取用一些未被使用的小于1024的端口来作为传输之用。但如此一来又造成客户端要连接服务器时的困扰,因为客户端要知道服务器端的相关端口才能够联机,此时我们需要远程过程调用(RPC)的服务。
RPC最主要的功能就是指定每个NFS功能所对应的端口号,并且回报给客户端,让客户端可以连接到正确的端口上。当服务器在启动NFS时会随机选用数个端口,并主动地向RPC注册。因此RPC可以知道每个端口对应的NFS功能。然后RPC固定使用端口111来监听客户端的请求并回报客户端正确的端口,所以可以让NFS的启动更为容易。
注意,启动NFS之前,要先启动RPC服务;否则NFS无法向RPC注册。另外,重新启动RPC时原本注册的数据会不见,因此RPC重新启动后它管理的所有程序都需要重新启动以重新向RPC注册,比如NFS服务。
当客户端有NFS文件要存取请求时,它向服务器端访问数据,有如下几个步骤:
(1)客户端会向服务器端的RPC(port 111)发出NFS文件存取功能的询问请求。
(2)服务器端找到对应的已注册的NFS daemon端口后会回报给客户端。
(3)客户端了解正确的端口后,就可以直接与NFS守护进程来联机,然后访问数据。
其实,我们可以简单的理解为:NFS当作RPC服务中的一种,同时将RPC服务当作NFS服务器与NFS客户端的中间接口人,就是说NFS客户端访问NFS服务器,必须经过RPC这个接口人,才可以去访问,否则就直接死翘翘了。
注:NFS使用TCP/IP提供的协议和服务,并且位于OSI模型中的应用层,具体如下:
层 数
名 称 功 能
1
应用层 NFS
2
表示层 XDR
3
会话层 RPC
4
传输层 UDP,TCP
5
网络层 IP
6
数据链路层
7
物理层 Ethernet
3
安装和配置NFS服务(只介绍SUSE版本的NFS的安装)
3.1.1
安装NFS服务
此步骤就直接跳过了,具体需要哪些包,可以到已经安装NFS服务的环境上面查看。
执行命令即可查看:rpm -qa | grep nfs
配置NFS服务,分为客户端和服务端配置。
3.1.2
服务端配置,设定10.137.21.166为NFS服务器:
步骤如下:
1)服务端主要配置/etc/exports文件。
我们将需要共享出去的文件系统直接编辑到/etc/exports文件中,这样当NFS服务器重新启动时,系统就会自动读取/etc/exports文件,从而告诉内核要输出的文件系统和相关的存取权限。
查看一个已经配置好的exports文件,如下:
i2ksvr:~ # cat /etc/exports
/home/cabtimer/sharedisk/index/share 10.137.17.154(rw,async)
/home/impidx/sharedisk/searchidx *(rw,sync,anonuid=2900,all_squash)
注:下面介绍一些配置文件中常用的参数含义,以及客户端的IP地址的格式。
rw:可读写权限。
ro:只读权限。
no_root_squash:当登录NFS服务器主机使用共享目录的使用者是root时,其权限将被转换成为匿名使用者,通常它的UID与GID都会变成nobody身份。
root_squash;如果登录NFS主机使用共享目录的使用者是root,那么对于这个共享的目录来说,它具有root的权限,这样会涉及到安全性的问题。
all_squash:忽略登录NFS使用者的身份,其身份都会被转换为匿名使用者,通常即nobody。
anonuid:通常为nobody,也可以自行设定这个UID的值,UID必须存在于/etc/passwd中。
anongid:同anonuid,但是变为Group ID。
sync:同步写入资料到内存与硬盘中。
async:资料会先暂存于内存中,而非直接写入硬盘。
共享给客户端的主机的IP地址可以使用以下格式。
单个机器:一个全限定域名(能够被服务器解析)、主机名(能够被服务器解析)或IP地址。
使用通配符来指定的主机名或域名,使用 * 或 ?字符来指定一个字符串匹配。IP地址中不使用通配符。
IP网络:使用a.b.c.d/z,a.b.c.d是网络,z是子网掩码中的位数(如192.168.0.0/24)。另一种可以接受的格式是a.b.c.d/netmask,a.b.c.d是网络,netmask是子网掩码(如192.168.70.8/255.255.255.0)。
一般常用的是IP地址,或直接用*代替,共享给所有的机器。
如上面举例的配置,一个指定了共享给固定IP的机器,另一个共享给所有的机器。
2)启动RPC服务
用法: /etc/init.d/portmap {start|stop|restart|force-reload|reload|status}
i2ksvr:~ # /etc/init.d/portmap start
Starting RPC portmap daemon done
(或直接执行rcportmap start)
查看状态
i2ksvr:~ # /etc/init.d/portmap status
Checking for RPC portmap daemon: running
查看111号端口是否处于监听状态和详细信息
i2ksvr:~ # netstat -utln | grep 111
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
udp 0 0 0.0.0.0:111 0.0.0.0:*
i2ksvr:~ # lsof -i :111
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
portmap 23048 nobody 3u IPv4 398290132 UDP *:sunrpc
portmap 23048 nobody 4u IPv4 398290133 TCP *:sunrpc (LISTEN)
可以看到会有TCP和UDP两个协议,之前NFS一直使用UDP协议,后来默认采用TCP协议了。
注:以上版本是SuSe 10或之前的版本,而SuSe 11版本开始有点不同,SuSe 11版本启动RPC服务的方式为/etc/init.d/rpcbind start
3)启动NFS Server服务
用法:/etc/init.d/nfsserver {start|stop|status|try-restart|restart|force-reload|reload}
i2ksvr:~ # /etc/init.d/nfsserver start
Starting kernel based NFS server done
(或直接执行rcnfsserver start)
查看状态:
i2ksvr:~ # /etc/init.d/nfsserver status
Checking for kernel based NFS server: running
4)查看共享出去的文件
执行showmount –e命令,查看共享的信息。查看本机时,不需要指定IP地址,此命令主要用在NFS客户端,用来查看NFS服务器共享出来的目录资源:
i2ksvr:~ # showmount –e
Export list for i2ksvr:
/home/impidx/sharedisk/searchidx *
/home/cabtimer/sharedisk/index/share 10.137.17.154
或执行
i2ksvr:~ # showmount -e 10.137.21.166
Export list for 10.137.21.166:
/home/impidx/sharedisk/searchidx *
/home/cabtimer/sharedisk/index/share 10.137.17.154
以上都说明NFS服务器共享成功了。
5)介绍其他一些常用的命令和文件,有的很重要。
exportfs命令
exportfs [-aruv]
参数说明如下:
-a:全部挂载(或卸载)/etc/exports文件内的内容。
-r:重新挂载/etc/exports中的设置,此外同步更新/var/lib/nfs/xtab文件中的内容。
-u:卸载某一目录。
-v:在export时将共享的目录显示在屏幕上。
比较常用的命令是:
exportfs –rv 使配置重新生效
如果修改了/etc/exports文件,执行该exportfs命令重新读取/etc/exports文件,从而就不需要重启NFS服务了。
showmount命令:
showmount [-ae] hostname
参数说明如下:
-a或-all:显示客户主机名和挂载点目录。
-d或-directories:仅显示被客户挂载的目录名。
-e或-exports:显示NFS服务器的输出清单。
-h或-help:显示帮助信息。
-v或-version:显示版本信息。
–no-headers:禁止输出描述头部的信息。
当要扫描某一主机所提供的NFS共享的目录时,使用showmount -e IP(或主机名称hostname)即可。
/var/lib/nfs/xtab和/var/lib/nfs/etab文件:
/var/lib/nfs/etab,主要记录了NFS所分享出来的目录的完整权限设定值;
/var/lib/nfs/xtab,记录曾经连接到此NFS主机的相关客户端数据。
6)设置NFS Server开机自启动
查看nfsserver服务的开机自启动状态,默认是任何启动状态都没有启动nfsserver的。
i2ksvr:~ # chkconfig --list nfsserver
nfsserver 0:off 1:off 2:off 3:off 4:off 5:off 6:off
设置nfsserver在开机为多用户模式和图形界面模式时,自启动nfsserver服务
i2ksvr:~ # chkconfig --level 35 nfsserver on
i2ksvr:~ # chkconfig --list nfsserver
nfsserver 0:off 1:off 2:off 3:on 4:off 5:on 6:off
3.1.3
客户端配置,设定10.137.17.154为NFS客户端:
推荐客户端使用mount命令来挂载,也可以直接编辑/etc/fstab文件的方法。
下面会介绍这两种方法:
1)使用mount命令挂载
mount命令的格式如下:
mount[-t vfstype] [-o options] device dir
mount命令参数非常多,下面就只列些常用的参数,红色标注的为重要部分:
(1)-a:把/etc/fstab中列出的路径全部挂载。
(2)-t:需要mount的类型,如nfs等。
(3)-r:将mount的路径定为read only。
(4)-v mount:过程的每一个操作都有message传回到屏幕上。
(5)rsize=n:在NFS服务器读取文件时NFS使用的字节数,默认值是1 024个字节。
(6)wsize=n:向NFS服务器写文件时NFS使用的字节数,默认值是1 024个字节。
(7)timeo=n:从超时后到第1次重新传送占用的1/7秒的数目,默认值是7/7秒。
(8)retry=n:在放弃后台mount操作之前可以尝试的次数,默认值是7 000次。
(9)soft:使用软挂载的方式挂载系统,若Client的请求得不到回应,则重新请求并传
错误信息。
(10)hard:使用硬挂载的方式挂载系统,该值是默认值,重复请求直到NFS服务器回应。
(11)intr:允许NFS中断文件操作和向调用它的程序返回值,默认不允许文件操作被中断。
(12)fg:一直在提示符下执行重复挂载,即前台继续执行挂载。
(13)bg:如果第1次挂载文件系统失败,继续在后台尝试执行挂载。
(14)tcp:对文件系统的挂载使用TCP,而不是默认的UDP。
(15)-w:将mount的路径定为read/write,这个是默认的配置参数。
重点说明一下软挂载和硬挂载方式的不同:
对硬挂载文件系统来说,如果因为某种原因远程系统的响应失败,比如NFS服务端挂掉等,则NFS客户端将会持续地尝试建立连接,这样可能导致执行df等命令出现挂死的现象。
而对软挂载文件系统来说,同样情况下,在指定的时间间隔后NFS客户端将会放弃尝试建立连接而发送一个错误消息。
默认采用硬挂载文件系统,系统硬挂载尝试失败时,对用户输入的响应也会停止。正是因为这样,有的用户更喜欢采用软挂载,它会使系统在尝试挂载失败后停止尝试。
其实,使用hard还是soft主要取决于访问的信息。例如,要查看NFS服务器的视频文件,不会希望由于一些意外的情况(如网络速度变得很慢)而使系统输出大量的错误信息。如果此时使用hard方式,系统就会等待,直到能够重新与NFS服务器建立连接传输信息。另外,如果是非关键数据,也可以使用hard方式,如FTP一些数据等,这样在远程机器暂时连接不上或关闭时就不会挂起会话过程。
mount挂载的示例:
mount -t nfs -o rw,soft,timeo=1,retry=1
10.137.21.166:/home/cabtimer/sharedisk/index/share /test
将NFS服务端的/home/cabtimer/sharedisk/index/share挂载到本地的/test目录下。
umount命令执行卸载的示例:
umount /test
注:如果umount挂载点时,出现长时间不返回,挂死的情况,如下解决:
通过lsof | grep /test找出哪个进程在访问挂载点;
确定该挂载目录不再访问的情况下,使用kill -9命令清理前面找出的访问挂载点的进程,再重新执行umount命令就可以了;
2)直接配置/etc/fstab文件
(1)编辑/etc/fstab文件,加入挂载NFS服务端的共享的目录到本地目录上,如下,加入了最下面的两行共享内容。
rcs_solution:~ # cat /etc/fstab
/dev/sda2 / reiserfs acl,user_xattr 1 1
/dev/sda5 /home reiserfs acl,user_xattr 1 2
/dev/sda6 /opt reiserfs acl,user_xattr 1 2
/dev/sda7 /var reiserfs acl,user_xattr 1 2
/dev/sda1 swap swap defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs noauto 0 0
debugfs /sys/kernel/debug debugfs noauto 0 0
usbfs /proc/bus/usb usbfs noauto 0 0
devpts /dev/pts devpts mode=0620,gid=5 0 0
shm /dev/shm tmpfs size=16348644K 0 0
10.137.21.166:/home/cabtimer/sharedisk/index/share /test nfs soft,timeo=1 0 0
(2)配置/etc/fstab文件后,直接启动NFS客户端,即可挂载NFS服务器共享的目录。
启动NFS Client:
/etc/init.d/nfs start
(或直接执行rcnfs start启动)
(3)执行df -h查看挂载的信息:
rcs_solution:~ # df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 61G 14G 47G 24% /
udev 16G 140K 16G 1% /dev
/dev/sda5 41G 21G 20G 51% /home
/dev/sda6 41G 35G 5.9G 86% /opt
/dev/sda7 11G 878M 9.2G 9% /var
shm 16G 6.3G 9.4G 41% /dev/shm
/dev/sda8 387G 25G 363G 7% /home1
10.137.21.166:/home/cabtimer/sharedisk/index/share
41G 21G 20G 51% /test
4
NFS的常见故障的解决方案
4.1.1
NFS如果出现了问题,可以从以下几个方面去考虑:
(1)/etc/exports文件配置是否正确
(2)RPC和NFS服务是否启动正常
(3)mount命令和/etc/fstab中的参数是否正确
(4)服务端的IP地址是否正常,能否ping通。
(5)执行rpcinfo命令查看系统的RPC相关的信息。
在服务端执行命令,可以看到如下的信息:
2ksvr:~ # rpcinfo -p
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 4 udp 2049 nfs
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100024 1 udp 45347 status
100021 1 udp 45347 nlockmgr
100021 3 udp 45347 nlockmgr
100021 4 udp 45347 nlockmgr
100024 1 tcp 38193 status
100021 1 tcp 38193 nlockmgr
100021 3 tcp 38193 nlockmgr
100021 4 tcp 38193 nlockmgr
100005 1 udp 785 mountd
100005 1 tcp 786 mountd
100005 2 udp 785 mountd
100005 2 tcp 786 mountd
100005 3 udp 785 mountd
100005 3 tcp 786 mountd
在NFS客户端,至少应该有portmapper。
4.1.2
NFS中的一些错误信息的具体含义:
错误信息
具体描述
Too many levels of remote in path
试图挂载一个存在的文件系统
Permission denied
客户端没有权限去挂载NFS服务器的共享目录,也可能是因为用户在服务器上不存在
No such file or directory
通常是访问的目录不存在
NFS server is not responding
通常是NFS已经超过负载或者NFS已经停止工作
Stale file handle
在NFS客户端关闭之前客户端访问的文件被删除
解决问题如下:
(1)如果启动NFS服务器失败,如下
i2ksvr:~ # /etc/init.d/nfsserver start
Starting kernel based NFS serverCannot register service: RPC: Unable to receive; errno = Connection refused
startproc: exit status of parent of /usr/sbin/rpc.mountd: 1
failed
则说明,RPC服务没有启动。如果已经启动,则可能是被防火墙所屏蔽。
解决方案是:执行/etc/init.d/portmap start后,再启动nfsserver即可。或者关闭防火墙。
(2)如果执行如下的mount命令失败,如下
i2ksvr:~# mount -t nfs 10.137.21.166:/home/cabtimer/sharedisk/index/share /test
rpcbind: server localhost not responding, timed out
RPC: failed to contact local rpcbind server (errno 5).
rpcbind: server localhost not responding, timed out
RPC: failed to contact local rpcbind server (errno 5).
解决方案是:在mount命令中加入-o nolock选项就可以了。
(3)当在客户端执行mount挂载NFS服务器共享目录时,如果错误信息是“Permission denied”,则表示NFS服务器不允许客户机挂载。
解决方案是:更改服务端上的/etc/exports文件来解决问题,并使用exportfs-rv命令重新导出共享目录。
(4)如果出现的错误是“Program not registed”,则是NFS服务可能没有启动或者运行不正常。
解决方案是:重新启动NFS服务。
(5)挂载共享目录的时候,如果客户端没有任何反应,则可能为客户端没有启动RPC服务。
解决方案是:启动portmap服务,然后再执行挂载的操作。
(6)显示“设备正忙”无法卸载。
在使用umount命令卸载共享目录时,出现“device is busy”等卸载失败消息。通常可能的原因是有一个进程仍然在使用这个目录。
解决方案是:可以使用lsof命令来查看是否有进程正在使用该共享目录,然后执行kill -9操作,杀掉这些进程,最后再执行umount操作。
(7)NFS请求挂起
如果客户端正在执行写操作,而此时服务器无法响应或者在网络上变得不可访问,那么在默认情况下(使用hard选项进行挂载)客户端进程将挂起直到写操作完成。如果不中止写操作,进程就不能从请求中退出。
解决方案是:这个需要根据实际的应用场合来考虑。一般情况下,为了避免NFS请求挂起,在网络状况不稳定情况下可以在挂载目录时指定soft选项以允许操作因超时而退出,或者指定intr选项以允许用户在命令行上通过按下Ctrl+C组合键退出挂起的操作。
(8)NFS挂载在引导时挂起。
如果在/etc/fstab文件中设置了自动挂载NFS,但在系统引导时NFS共享目录暂时不可用,那么默认情况下引导进程将进入等待状态,直到NFS目录变得可用为止。如果所需等待的NFS目录是系统必须的,那么这种等待可能还可以接受。然而在很多情况下,用户只想让系统把挂载请求放在后台并继续引导系统。可以把bg选项添加到/etc/fstab文件中,这样在首次挂载请求超时之后,挂载请求会转入后台,系统继续引导。当需要在前台挂载NFS共享目录时可以将fg选项添加到/etc/fstab文件的挂载选项中。
5
NFS客户端参数的优化
在一些业务当中,出现过因为NFS服务器的IP地址down掉,或者异常等情况,导致了NFS客户端访问进程的长时间处于挂死的状态,没有响应。
查看了NFS的官方网站,里面介绍了一些优化的参数,比如说,客户端需要加入
参数:soft,timeo=1,retry=1,tcp(默认就是采用tcp协议),其实就是采用软连接的方式去挂载NFS服务器共享的目录,这样NFS客户端就不会出现挂死的现象。
举例:
mount -t nfs -o rw,soft,timeo=1,retry=1
10.137.21.166: /home/cabtimer/sharedisk/index/share /test
6
附录:设置系统防火墙,开放portmap端口号
打开portmap的端口号
iptables -A INPUT -p TCP --dport 111 -j ACCEPT
iptables -A INPUT -P UDP --dport 111 -j ACCEPT
iptables-save > /etc/sysconfig/iptables
在文件/etc/hosts.allow文件中加入如下内容,允许这些服务访问:
portmap:ALL
nfsserver:ALL
nfs:ALL