NFS Linux 网络文件系统入门到实践
NFS:Linux 网络文件系统入门到实践
网络文件系统(NFS)
介绍
NFS的全称是Network FileSystem,即网络文件系统,NFS主要实现的功能是让网络上的不同操作系统之间共享数据。NFS首先在远程服务端(共享数据的操作系统)共享出文件或者目录,然后远端共享出来的文件或者目录就可以通过挂载(mount)的方式挂接到本地的不同操作系统上,最后,本地系统就可以很方便的使用远端提供的文件服务,操作起来像在本地操作一样。从而实现了数据的共享。
NFS服务器的主要进程
- rpc.nfsd 进程
NFS服务的主进程,主要管理客户端是否能够接入NFS服务器以及数据的传输,该进程固定监听TCP/UDP 2049端口号 - rpc.mountd 进程
管理和维护NFS文件系统,根据所设定的权限决定是否允许客户端挂载指定的共享目录,该进程监听的端口号默认是不固定的。 - rpc.lockd进程
提供文件锁功能,防止多个客户端同时写入一个文件,该进程监听的端口默认是不固定的。 - rpc.statd进程 RPC 的端口映射器进程,监听UDP111端口。
注意:2049端口UDP和TCP只能选择其中一种协议方式
NFS的特性:
- NFS的安全性方面
NFS默认没有加密,且仅依靠IP地址或主机名来决定是否运行客户端挂载指定的共享目录,但是NFS可以通过Kerberos进行认证及加密 - 共享资源的属主、属组和权限方面:
NFS服务器和客户端通过UID和GID来识别共享资源的所有者信息,当客户端挂载NFS共享目录时,共享目录中资源的UID和GID将与服务器上面的保持一致;而客户端会将UID和GID映射到客户端上所对应的用户名和组名。
例如:
服务器上有名为server的用户,其UID为111:客户端上有名为client的用户,其UID同为111。那么,UID为111的共享资源在服务器上的属主是server;在客户端上的属主则是client。这样的话可以继承服务器的gid属组acl与权限的问题。
那么如果UID或GID没有对应的用户或组时,那么用户名或组名将直接以UID或GID表示。例如:客户端上有名为client的用户,其UID为222:而服务端上没有UID为222的用户。那么,UID为222的共享资源在服务器上的属主将直接用222表示:在客户端上的属主则是client,NFS服务器与客户端上共享资源的权限及ACL信息(若支持)将保持一致I
NFS服务端部署
| 角色 | 主机名 | IP 地址 | 操作系统版本 |
|---|---|---|---|
| NFS-Server | centos-manager | 10.201.9.134 | CentOS Linux 7 |
| client1 | node1 | 10.201.9.133 | CentOS Linux 7 |
| client2 | node2 | 10.201.9.140 | CentOS Linux 7 |
- 检查NFS-Server上是否已经存在NFS服务命令如下:
rpm -qa | grep nfs
1 | |
如果存在nfs-utils的软件包说明已经安装了nfs服务了,无需再继续安装。没有的话,可以使用yum安装
NFS配置文件
/etc/exports,这是nfs的配置文件,打开之后是空白的,需要自行编辑基本语法:
<共享目录> <客户端1>(选项1,选项2,...) <客户端2>(选项3,...) ...
客户端表达方式示例:
| 表达式 | 含义说明 |
|---|---|
10.201.9.133 |
单个 IP 地址 |
10.201.9.0/24 |
整个子网(CIDR 表示法) |
*.example.com |
所有 example.com 域中的主机 |
client1.local |
指定主机名(需 DNS 或 /etc/hosts 解析) |
* |
所有客户端(不推荐,存在安全风险) |
常用导出选项:
| 选项 | 说明 |
|---|---|
rw |
允许客户端读写(默认是只读 ro) |
ro |
只读访问 |
sync |
同步写入(数据写入磁盘后才返回确认,更安全,默认行为) |
async |
异步写入(性能更好,但断电可能丢数据) |
no_root_squash |
允许客户端 root 用户保留 root 权限(高危!慎用) |
root_squash |
将客户端 root 映射为匿名用户(如 nfsnobody),默认启用 |
all_squash |
所有客户端用户(包括 root)都映射为匿名用户 |
anonuid=xxx |
指定匿名用户的 UID(配合 all_squash 或 root_squash 使用) |
anongid=xxx |
指定匿名用户的 GID |
no_subtree_check |
禁用子树检查(提升性能,适用于整个文件系统被共享的情况) |
subtree_check |
启用子树检查(默认,但可能影响性能) |
no_all_squash |
保留共享文件的UID和GID(默认) |
- 配置实例
1 | |
解释:
/tmp *(rw,all_squash,anonuid=65534,anongid=65534,no_subtree_check) 任何网络中的主机都能挂载并读写该共享(因使用了 *),无论客户端以什么用户(包括 root)挂载并操作 /tmp 共享目录,所有新建/修改的文件在 NFS 服务器上都显示为 属主 UID=65534, GID=65534。
/root 10.201.9.140(rw,no_root_squash) 10.201.9.133(ro,no_root_squash) 将 /root 目录共享,允许 10.201.9.140 读写、10.201.9.133 只读,且两者均保留 root 权限(no_root_squash)
该配置将 /netaccess 目录以异步读写方式共享给 10.201.9.140,且匿名用户被设为 UID/GID 65534。
当前我的系统是没有netaccess目录的,所以需要创建一个
1 | |
在 Linux 系统中,UID(用户 ID)65534 通常是一个特殊的保留 UID,用于表示 “nobody” 或 “nfsnobody” 用户,这个用户是 NFS 服务在启用 root_squash 或 all_squash 时,用来映射远程客户端用户的匿名用户。它没有登录 shell,也不属于任何特权组,权限极低,仅用于安全隔离。
- 启动NFS服务
命令:systemctl start nfs
检查端口是否启动,主要检查rpcbing的UDP111端口和nfsd的2049端口
1 | |
可以使用exportfs -arv 查看当前服务共享出去的目录
1 | |
客户端挂载
在客户端上可以使用showmount -e nfs服务器IP地址 可以查看nfs服务器输出目录,showmount 命令是依赖于nfs-utils软件包的,如果没有这个命令的话,需要使用yum -y install nfs-utils 进行安装一下客户端上只要安装即可,不需要启动nfs服务
1 | |
- 挂载
挂载tmp目录
1 | |
noatime 挂载时不更新文件访问时间
rsize 读取块大小为 1 MB
wsize 写入块大小 为1MB
挂载之后使用df -h 命令查看挂载情况
1 | |
可以看到tmp目录已经成功挂载到了nfs主机上的/tmp目录上了
测试
在node2的客户端上挂载的tmp目录创建一个文件,删除一个文件,并在nfs服务端查看
1 | |
1 | |
可以看到我们在客户端挂载的tmp目录中,创建了两个txt的文件,在nfs服务器中也能正常看到,并且他的归属组和归属主是nfsnobody,这是因为我们在nfs服务器上面挂载的时候配置了all_squash(将客户端 root 映射为匿名用户),并且指定了匿名用户的gid和uid为65534,65534这个id对于的就是nfsnobody用户。
挂载root目录
1 | |
测试
1 | |
1 | |
在客户端挂载的root目录创建一个文件,在nfs服务器同样可以正常看到,只是该文件的归属组和归属主没有映射为匿名用户,而是直接显示的root,因为我们在配置挂载的时候启用了这个参数no_root_squash(允许客户端 root 用户保留 root 权限)
在10.201.9.133也就是node1上挂载测试
1 | |
可以看到我们在配置root目录共享的时候,133是只有只读权限的。
1 | |
1 | |
因为没有写入权限,所以即使是root权限也是无法写入的。
客户端自动挂载
如果想要是自动挂载的话,这个时候就需要使用到/etc/fastab文件了,在10.201.9.133 也就是node2上自动挂载root目录进行举例
1 | |
挂载选项详解
| 选项 | 说明 |
|---|---|
auto |
允许通过 mount -a 自动挂载(默认行为,通常可省略) |
ro |
只读挂载(Read-Only),客户端无法修改内容 |
vers=4 |
使用 NFSv4 协议 |
hard |
硬挂载:若服务器无响应,客户端会持续重试(保证数据一致性,但可能导致进程卡住) |
intr |
允许用 Ctrl+C 中断因服务器无响应而挂起的操作(在 hard 模式下有效)注:Linux 内核 2.6.25+ 后此选项已废弃,但保留兼容性 |
tcp |
使用 TCP 作为传输协议(NFSv4 默认即 TCP,可省略) |
rsize=32768 |
读取缓冲区大小为 32KB(合理值,常见范围 32K–1M) |
wsize=32768 |
写入缓冲区大小为 32KB(同上) |
hard + intr(旧内核)曾用于允许中断挂起操作,但 Linux 2.6.25+ 后 intr 已废弃,hard 模式下信号(如 Ctrl+C)默认可中断。
测试
在node2中将root目录进行卸载
1 | |
使用mount -a 再继续重新挂载,查看是否能够重新挂载回来,如果可以挂载回来说明自动挂载配置成功
1 | |
autofs自动挂载服务
autofs 是 Linux 中一个 自动挂载文件系统 的服务,特别适用于按需挂载 NFS、CIFS、本地目录等,在访问时自动挂载,空闲一段时间后自动卸载,避免系统启动时因网络存储不可用而卡住,也节省资源。
autofs自动挂载服务优势
- 可以隐藏父目录,提高安全性。
- 完美解决由于网络故障而导致服务器宕机的情况。
- 高并发状态下可以大量节约网络与服务器资源。
autofs需要从/etc/auto.master文件中读取配置信息。该文件中可以同时指定多个挂载点,由autofs来挂载文件系统

如图:我需要将NFS的/netaccess目录使用autofs挂载到NFSClient的/web目录中的话,就需要再NFSClient中安装一个autofs的服务,并且编写配置文件
在NFSServer上的/netaccess中创建一个web目录
1 | |
- 查看NFSClinet系统是否已经安装autofs。
1 | |
- autofs配置文件
主配置文件:/etc/auto.master 定义 autofs 管理的挂载点根目录及其对应的子映射文件或程序
子映射文件:/etc/auto.(如 /etc/auto.nfs) 定义具体挂载项,即在父目录下创建哪些子目录、挂载什么资源、使用什么选项。
特殊映射文件:/etc/auto.misc 用途:autofs 默认提供的示例文件,包含常见挂载模板(CD-ROM、软盘等) - 修改配置文件
1 | |
将模板文件复制并重命名为自定义的配置文件并进行修改
1 | |

1 | |
这里的soft的含义是使用“使用软挂载模式”,当 NFS 服务器无响应(如宕机、网络中断)时,客户端会在重试若干次后直接返回 I/O 错误,应用程序会立即收到错误,而不是无限等待。
- 启动autofs服务
1 | |
因为在编写/etc/auto.web的时候使用了autofs 通配符挂载配置。要触发挂载,需要访问 /web 下的某个具体子目录,但是这个目录必须是要NFSServer共享目录中所存在的,在之前我们已经在netaccess目录中创建了一个web目录了,可以访问web目录触发挂载
- 测试
1 | |
使用 ls /web/web 这会触发 autofs 将 10.201.9.134:/netaccess/web 挂载到 /web/web
设置NFS版本为V4版本
查看当前nfs服务器端支持的nsf版本
1 | |
服务器端
- 编辑
/etc/sysconfig/nfs配置文件
1 | |
- 重启nfs服务
1 | |
客户端
- (非必须)编辑
/etc/sysconfig/autofs配置文件
这是autofs自动挂载服务的配置文件,在配置文件最后一行添加MOUNT_NFS_DEFAULT_PROTOCOL = 4.2
1 | |
- 必须配置
编辑/etc/auto.web的配置文件,指定版本号
1 | |
- 重启autofs 自动挂载服务
1 | |
使用mount | grep /web/web 可以看到nfs的版本号就变成了v4.2版本
如果要使用mount挂载的时候使用v4.2版本的话,直接在挂载命令中加上vers=4.2即可
1 | |
NFS设置固定端口号
之前我们提到过,在NFS中,固定的端口号一共有两个,分别是rpc.nfsd 主进程的2049和rpc.statdRPC 端口映射进程的UDP111端口号,除此以外,还有四个进程是使用的随机端口号
以下是 NFS 相关服务及其默认可能使用随机端口的组件:
| 服务名称 | 程序号 (Program Number) | 默认是否使用随机端口 | 主要协议 | 功能说明 |
|---|---|---|---|---|
rpc.mountd |
100005 | ✅ 是 | TCP/UDP | 处理客户端挂载/卸载请求 |
rpc.statd (NSM) |
100024 | ✅ 是 | TCP | 监控主机状态,用于锁恢复(Network Status Monitor) |
lockd (NLM) |
100021 | ✅ 是 | TCP/UDP | 实现文件锁机制(Network Lock Manager) |
rpc.rquotad |
100011 | ✅ 是 | TCP/UDP | 提供磁盘配额查询服务 |
NFS 本身依赖多个辅助守护进程来提供完整功能,而这些服务默认通常使用随机高端口(由 rpcbind 动态分配),这在防火墙或安全策略严格的环境中会带来问题。因此,固定这些服务的端口是一种常见的做法,便于配置防火墙规则。
如果需要将以上四个进程的端口号固定的话,就可以用通过修改/etc/sysconfig/nfs NFS的配置文件实现
- 修改配置文件如下:
1 | |
- 重启服务
这里需要重启NFS、rpcbind 和rpc-statd服务
1 | |
- 检查端口是否监听
1 | |
rpc.rquotad,磁盘配额查询服务因为我在配置中没有开启,所以这里查不到端口号是正常的。
NFS挂载写入失败 注意事项:
| 误区 | 事实 |
|---|---|
“客户端写了 -rw 就能写” |
❌ 服务器说了算 |
“挂载显示 rw 就能写” |
❌ 可能因 UID 权限被拒 |
| “导出父目录就能挂子目录” | ❌ NFSv4 需显式导出子路径(除非用 fsid=0 伪根) |
总结:NFS 的写权限 = 服务端 exports 的 rw + 服务端文件系统对 nfsnobody 可写。