☰
NFS 一挂就权限拒绝?CentOS 7 共享挂载 + 踩坑清单
2026/9/30 16:08:53 网站建设 项目流程

NFS 挂载卡在超时,十有八九是防火墙只放行了nfs、把 111 和 113 两种报错混为一谈,连 root 写不进去都当成故障。本文先讲清 NFS「先向 RPC 要端口」的工作链路,再把/etc/exports的客户端匹配写法与导出选项逐条列清,接着走一遍服务端导出、客户端挂载、fstab持久化,最后给出 RPC 报错的读法与errno代码对照表。文中命令名与选项均标注英文原意,完整清单见文末《附:命令英文全称速查表》。

本文概要:

项目内容
文章主题NFS 网络文件共享:RPC 工作链路 → 服务端导出配置 → 客户端挂载验证 → fstab 持久化与排错
所属类别Linux 系统管理 → 网络存储 → NFS
知识关键字nfs-utils·/etc/exports·/etc/exports.d·exportfs·showmount·mount -t nfs·rpcinfo·rw·ro·root_squash·no_root_squash·/etc/fstab·_netdev·nofail·RPC·errno 111/113·NFSv3·NFSv4

概念图给出两条并行的读写链路:本地访问不出网络,远程访问必须先由 RPC 拿到服务端口。概要表里的关键字按主线落在:RPC 与工作流程在第一章,导出写法与选项在第二章,客户端挂载在第三章,持久化与排错在第四、五章。

本文的机器与地址约定:服务端zhb-s2(10.1.8.102),客户端zhb-m2(10.1.8.12),共享网段10.1.8.0/24。

一、NFS 服务介绍

1.1 NFS 是什么

NFS(NetworkFileSystem,网络文件系统)诞生于 20 世纪 80 年代。它由太阳微系统公司(Sun Microsystems)开发,最初用来解决 UNIX 系统之间的文件共享。客户端可以像访问本地文件一样透明地访问远程目录,跨设备共享数据不必再靠人工拷贝。

版本迭代上,NFSv3 是应用最广的版本,支持更大的文件尺寸与更多功能;NFSv4引入了 Kerberos 认证、状态化连接与更完善的文件锁机制,安全性明显更强。

1.2 两个角色

角色职责
NFS 服务器存储文件资源,由nfsd守护进程响应请求,用/etc/exports控制哪些目录共享给谁、给什么权限
NFS 客户端把服务端共享目录挂载到本地挂载点,之后按普通文件读写,数据实际落在服务端磁盘

1.3 工作链路:先向 RPC 要端口

NFSv3 服务端的端口并不固定。启动时它会把端口注册到 RPC 的端口映射服务(RemoteProcedureCall,远程过程调用)。客户端要先查出端口,才能发出挂载请求:

  1. 注册阶段:服务端启动 NFS 服务,把服务端口注册给 RPC。
  2. 建立连接:客户端先向 RPC 查询 NFS 服务端口,再向该端口发起挂载请求。
  3. 挂载阶段:服务端校验客户端身份与权限,通过后允许挂载到指定挂载点。
  4. 文件访问:挂载成功后,本地读写被转成远程过程调用,服务端执行后把结果返回。
  5. 权限控制:服务端按本地文件系统的 UID / GID 与导出选项决定是否放行。

⚠️注意:正因为端口要向 RPC 注册,服务端防火墙必须同时放行nfs、rpc-bind、mountd三项;只放行nfs会出现「客户端探测不到共享、挂载卡住」。

1.4 优缺点与典型场景

维度说明
优点透明(用法与本地目录一致)、跨平台(UNIX / Linux / macOS)、配置简单、便于集中管理
缺点NFSv3 及更早版本缺少强认证与加密,高安全场景要配合防火墙或改用 NFSv4 的 Kerberos;性能强依赖网络状况;多客户端并发写同一文件时锁机制复杂

典型场景:企业局域网内共享文档与安装包;Web、数据库集群的统一共享存储;NAS、路由器等嵌入式设备的文件对外访问。

二、部署 NFS 服务端

2.1 六步总览

步骤做什么用哪条命令
1安装软件包yum install -y nfs-utils
2准备共享目录与属主mkdir -p、chown
3写导出配置vim /etc/exports
4启用并启动服务systemctl enable nfs-server --now
5放行防火墙firewall-cmd --permanent --add-service=...
6重新导出并自查exportfs -r、exportfs -v
# 1. 安装软件包[root@zhb-s2 ~]# yum install -y nfs-utils# 2. 准备用户与共享目录,属主交给 apache(UID 48)[root@zhb-s2 ~]# useradd -u 1000 zhb[root@zhb-s2 ~]# echo redhat | passwd --stdin zhb[root@zhb-s2 ~]# mkdir -p /shares/webapp[root@zhb-s2 ~]# chown 48 /shares/webapp# 3. 写导出配置(写法见 2.2、2.3)[root@zhb-s2 ~]# vim /etc/exports# 4. 启用并启动服务[root@zhb-s2 ~]# systemctl enable nfs-server --now# 5. 配置防火墙(nfs / rpc-bind / mountd 三项都要放)[root@zhb-s2 ~]# firewall-cmd --permanent --add-service=nfs --add-service=rpc-bind --add-service=mountd[root@zhb-s2 ~]# firewall-cmd --reload

⚠️注意:NFS 不要使用 SMB 共享的目录。如果这样做,则可能会导致文件损坏或其他文件完整性与一致性问题。

2.2 配置文件与目录

导出规则写在/etc/exports;另外/etc/exports.d/下任何以.exports结尾、且不以点(.)开头的文件同样生效,语法完全一致。

提示:相比直接编辑/etc/exports,在/etc/exports.d/里创建或删除独立文件更省事,也能减少一次改动误伤其他已有导出的风险。

每一行声明一个导出点:第一个字段是服务端目录,其余部分列出可以访问它的客户端以及授予的权限。

2.3 客户端匹配写法速查表

写法作用说明(英文原意)
/shares/webapp zhb-m2.zhb.cloud单个可解析主机名只放行这一台
/shares/webapp *.zhb.cloud域名通配*匹配zhb.cloud域下所有主机
/shares/webapp 10.1.8.12单个 IPv4 地址只放行这一台
/shares/webapp 10.1.8.0/24IPv4 网段等价写法10.1.8.0/255.255.255.0
/shares/webapp fde2:6494:1e09:2::20单个 IPv6 地址—
/shares/webapp fde2:6494:1e09:2::/64IPv6 网段—
/shares/webapp 10.1.8.0/24 zhb-m2.zhb.cloud多客户端空格分隔的列表

2.4 导出选项速查表

目录默认以只读方式共享;要改权限,在客户端定义后面紧跟括号写选项,客户端定义与左括号之间不能有空格。

写法作用说明(英文原意)
(rw)允许读 / 写read-write;不写该选项(或写ro)就只有读权限
(ro)只读read-only
(no_root_squash)保留客户端 root 的真实身份默认是root_squash:客户端 root 访问时被映射成服务端的nobody,创建的文件属主变成nobody,读取也按nobody判权限
(sync)数据落盘后才返回synchronous,默认值,安全优先
(async)先返回、后落盘性能更好,异常掉电有丢数据风险
(no_subtree_check)关闭子树检查subtreecheck,减少导出子目录时的额外校验

本实验的记录:

[root@zhb-s2 ~]# vim /etc/exports/shares/webapp10.1.8.0/24(rw)

⚠️注意:/etc/exports改完不会自动生效,必须让导出表重新加载,否则客户端看到的仍是旧规则。

2.5 让改动生效

[root@zhb-s2 ~]# exportfs -r # 重新导出:与 /etc/exports 同步,并清掉已删除的条目# 或者[root@zhb-s2 ~]# systemctl reload nfs-server# 或者[root@zhb-s2 ~]# exportfs -av

2.6 exportfs 用法速查表

写法作用说明(英文原意)
exportfs列出当前导出的目录不显示导出选项
exportfs -v列出导出及选项verbose,含默认选项
exportfs -r重新导出全部目录re-export,把/var/lib/nfs/etab与/etc/exports同步
exportfs -a导出/etc/exports中的全部条目all
exportfs -u <目录>取消导出一个目录unexport
exportfs -s以/etc/exports的格式打印导出表show
[root@zhb-s2 ~]# exportfs/shares/webapp10.1.8.0/24[root@zhb-s2 ~]# exportfs -v/shares/webapp10.1.8.0/24(sync,...,rw,secure,no_root_squash,...)

三、客户端访问与验证

3.1 showmount 用法速查表

写法作用说明(英文原意)
showmount -e <服务端>查看服务端导出的共享清单exports
showmount -a <服务端>列出已挂载的客户端all
showmount -d <服务端>列出被客户端挂载的目录directories

3.2 挂载并验证读写

# 客户端装包,并准备 Web 服务[root@zhb-m2 ~]# yum install -y nfs-utils httpd[root@zhb-m2 ~]# id apacheuid=48(apache)gid=48(apache)组=48(apache)[root@zhb-m2 ~]# systemctl enable httpd --now# 查看服务端提供的共享[root@zhb-m2 ~]# showmount -e zhb-s2Export listforzhb-s2: /shares/webapp10.1.8.0/24# 挂载到站点目录[root@zhb-m2 ~]# mkdir -p /var/www/html[root@zhb-m2 ~]# mount -t nfs zhb-s2:/shares/webapp /var/www/html# root 不能创建:默认 root_squash 把 root 压成了 nobody[root@zhb-m2 ~]# touch /var/www/html/root-f1touch: cannottouch‘/var/www/html/root-f1’: Permission denied# apache 用户能创建:UID 48 在服务端目录上就是属主[root@zhb-m2 ~]# su -l -s /bin/bash apache-bash-4.2$echoapache website>/var/www/html/web1.html
# 回到服务端访问客户端站点,确认共享目录里的内容真的落盘可读[root@zhb-s2 ~]# curl http://10.1.8.12/Welcome to zhb website.[root@zhb-s2 ~]# curl http://10.1.8.12/web1.htmlapache website

3.3 mount -t nfs 常用选项速查表

写法作用说明(英文原意)
mount -t nfs zhb-s2:/shares/webapp /mnt基础挂载-t=type;nfs可省略,由内核自动识别
mount -o ro ...只读挂载read-only
mount -o hard ...服务端无响应时一直重试默认行为,适合有稳定网络的场景
mount -o soft ...服务端无响应时超时报错返回避免进程被挂起,但可能读到不完整数据
mount -o vers=4 ...指定 NFS 版本version,如vers=3/vers=4.2

四、持久化挂载

在/etc/fstab末尾追加一行:

zhb-s2:/shares/webapp /var/www/html nfs defaults,_netdev,nofail 0 0
选项作用说明
defaults基础默认集即rw,suid,dev,exec,auto,nouser,async七个选项的简写
_netdev声明「该挂载依赖网络」让 systemd 按网络挂载处理:排进remote-fs-pre.target→remote-fs.target区间,并拉起network-online.target、排在其后——网络没就绪前不会先去挂
nofail允许挂载失败该条目只被 target「想要(Wants=)」而非「必需(Requires=)」,挂不上也不阻塞启动、不进 emergency 模式

⚠️这两个选项管的是两件不同的事,别混为一谈:_netdev管「什么时候挂」(等网络就绪再挂),nofail管「挂不上会怎样」(不挡启动)。少了nofail,服务端一旦不可达,启动阶段就会卡在这一行上等它超时,严重时掉进 emergency shell。

💡可选加强:等待设备/挂载的默认超时约 90 秒,觉得太久可再加x-systemd.device-timeout=30(单位可写s、min),把等待压到 30 秒——写法为defaults,_netdev,nofail,x-systemd.device-timeout=30。该选项只能写在/etc/fstab里,写进 systemd 单元文件的Options=会被忽略。

⚠️注意:NFS 条目本身就会被 systemd 按文件系统类型识别为网络挂载、排进remote-fs.target体系,所以_netdev在 NFS 上更多是「显式声明」,写不写都能工作;但在iSCSI 这类 fstype 只是ext4/XFS、看不出依赖网络的挂载上,_netdev是必需的。另外nofail只保证「不挡启动」,不等于挂上了——依赖这个挂载点的服务(如 httpd)照样会起不来,所以 fstab 改完先跑mount -a确认不报错。

五、排错速查

5.1 读懂一条 RPC 报错

showmount与mount -t nfs的报错几乎都出在 RPC 层,格式固定,按段拆开读就能定位:

clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host)
段报错片段含义说明
①clnt_create客户端创建 RPC 连接失败卡在「连得上吗」这一步,与导出规则、权限无关
②Port mapper failure连不上 RPC 端口映射服务即 111 端口上的rpcbind;这一段失败说明连 111 端口都不通
③Unable to receive请求已发出,但没有收到回包典型是防火墙丢包,而不是端口没人监听
④errno 113 (...)具体原因码见 5.2 对照表

5.2 常见 errno 代码对照表

RPC / NFS 报错末尾括号里的errno N是标准系统错误号,含义固定:

errno宏名含义(英文原意)触发场景
101ENETUNREACHNETworkUNREACHable,网络不可达本地路由表没有到目标网段的条目
110ETIMEDOUTTIMEDOUT,连接超时请求发出去无人应答:中间链路不通或被静默丢包
111ECONNREFUSEDCONNectionREFUSED,连接被拒绝对端回了 RST:端口没有程序监听,或被主动拒绝
112EHOSTDOWNHOSTDOWN,主机已关闭对端主机宕机
113EHOSTUNREACHHOSTUNREACHable,无路由到主机收到 ICMP 主机不可达,或包被防火墙静默丢弃
116ESTALESTale file hANDLE,文件句柄失效服务端导出被重建或重启,客户端缓存的句柄过期
4EINTRINTerrupted system call,系统调用被中断读写被信号打断,重试即可
5EIOInput/Output error,输入输出错误连接中断后仍在读写,或后端存储异常
13EACCESACCess denied,权限不足导出选项或 UID 映射导致写不进去
30EROFSRead-OnlyFileSystem,只读文件系统以只读方式导出或挂载时执行了写入
121EREMOTEIOREMOTEI/Oerror,远端 I/O 错误NFS 服务端读写失败后传回的错误

提示:本机可查完整清单——man 3 errno看名字与描述,装了moreutils的机器用errno -l一次列出全部编号。

5.3 「连接被拒绝」与「无路由到主机」的区别

同样是连不上,111 与 113 的病因完全不同,这张表能省掉大半排查时间:

报错网络层发生了什么通常意味着
errno 111 (Connection refused)目标主机回了 RST——包已经送达主机,只是该端口没有程序监听rpcbind没启动,或防火墙用的是 REJECT 策略
errno 113 (No route to host)收到 ICMP 主机不可达,或包被静默丢弃,客户端等到超时也没回包防火墙用的是 DROP 策略、路由不通、主机不在线

判据:能ping通服务端却报 113,几乎可以断定是服务端防火墙把 RPC 相关端口挡了。先用rpcinfo -p <服务端>验证 111 端口通不通,再检查firewall-cmd --list-services里有没有rpc-bind、nfs、mountd三项。

# 客户端:探测服务端注册了哪些 RPC 服务(能列出 portmapper / mountd / nfs 才算通)[root@zhb-m2 ~]# rpcinfo -p zhb-s2# 服务端:确认三项服务都已放行[root@zhb-s2 ~]# firewall-cmd --list-services

5.4 报错原文与处理速查表

报错原文成因处理
clnt_create: RPC: Port mapper failure ... errno 113服务端防火墙未放行 RPC / NFS 端口,包被丢弃放行rpc-bind、nfs、mountd后firewall-cmd --reload
clnt_create: ... errno 111 (Connection refused)服务端rpcbind没启动,或端口被主动拒绝systemctl enable --now rpcbind nfs-server
RPC: Program not registeredrpcbind在跑,但mountd/nfsd没注册(NFS 服务没起)服务端rpcinfo -p是否列出mountd与nfs;systemctl restart nfs-server
mount.nfs: Connection timed out请求无响应,中间链路或目标防火墙丢包逐跳排查防火墙;rpcinfo -p、telnet <服务端> 2049
mount.nfs: access denied by server while mounting客户端 IP 不在/etc/exports匹配范围内,或改完没重载核对匹配写法;执行exportfs -r
mount.nfs: reason given by server: No such file or directory请求的目录路径写错,或该目录根本没被导出用showmount -e <服务端>核对导出路径拼写
mount.nfs: requested NFS version or transport protocol is not supported客户端用了服务端不支持的版本或协议加-o vers=3或-o vers=4.2指定;服务端rpcinfo -p看注册的版本
mount.nfs: Network is unreachable本地路由表没有目标网段条目检查网卡与路由ip route
挂载成功但写不进去(Permission denied)导出选项没给(rw),或客户端操作用户的 UID 与服务端目录属主不一致改(rw)后exportfs -r;核对两端 UID
root 写不进去、换普通用户就能写默认root_squash在起作用属正常现象;确需保留 root 身份再加(no_root_squash)
Stale file handle(errno 116)服务端导出被重建或重启,客户端句柄失效卸载后重新挂载;必要时umount -l再mount
读写报Input/output error(errno 5)连接中断后仍在读写,或服务端存储故障查dmesg与网络状态;卸载重挂
umount报device is busy有进程正占用挂载点lsof +D <挂载点>找出占用进程,先离开挂载点再卸载
开机卡住不动、服务端不可达时掉进 emergencyfstab 条目默认是Requires=,启动会等它挂完挂载选项补_netdev,nofail;仍嫌等得久再加x-systemd.device-timeout=30
重启后挂载点空着、df里看不到该目录挂载失败但被nofail放过了,不会报错中断启动systemctl status var-www-html.mount看失败原因;确认网络与nfs-server已就绪

附:命令英文全称速查表

命令 / 缩写英文全称 / 原意作用
NFSNetworkFileSystem网络文件系统
RPCremoteprocedurecall远程过程调用,NFS 依赖它做端口映射
rpcbind/portmapRPCbind/portmap把 RPC 服务号映射到监听端口的服务
rpcinfoRPCinformation查询某主机注册了哪些 RPC 服务及其端口
exportfsexportfilesystem维护服务端导出表
showmountshowmount查询服务端共享与客户端挂载
mountdmountdaemon处理客户端挂载请求的守护进程
nfsdNFSdaemon内核态的 NFS 服务线程
nobodynobody匿名用户,root_squash之后的映射身份
UID/GIDuserIDentifier /groupIDentifier用户标识号 / 组标识号

📚 参考资料(官方文档 · 中英双语)

官方手册(Ubuntu manpages)

  • exports(5):NFS 服务端导出表格式与全部选项
  • exportfs(8):导出表维护命令
  • nfs(5):fstab 里 NFS 挂载选项与传输方式
  • systemd.mount(5):fstab 里nofail、_netdev等 systemd 专用挂载选项

中文版

  • mount 命令中文说明(菜鸟教程)

其余手册在服务器上直接查:

man5exports# 导出表语法与全部选项man8exportfs# 导出表的维护动作man5nfs# fstab 里的挂载选项man5systemd.mount# fstab 里的 nofail / _netdev / x-systemd.* 选项man8showmount# 查看服务端共享man8rpc.mountd# 挂载请求的守护进程

总结:NFS 的配置就三件事——注册(服务端把端口交给 RPC,客户端才找得到)、匹配(/etc/exports决定放行哪些客户端)、映射(导出选项与 UID 决定文件落到服务端后归谁)。改完配置先exportfs -r再验证,遇到被拒先看客户端 IP 有没有落在匹配范围内。觉得有用可以收藏,access denied或写权限的问题欢迎在评论区聊聊排查过程。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询