暗色模式

NFS 网络文件共享:从服务端导出到客户端挂载与权限配置

技术教程
2026-08-30
6
0
本文要点
  • NFS(网络文件系统)让多台 Linux 主机通过网络共享同一份目录,客户端挂载后如同本地磁盘使用
  • 服务端用 /etc/exports 声明导出目录与允许的主机,exportfs -ra 应用,showmount -e 验证
  • 客户端 mount -t nfs 挂载后即可读写;NFSv4 默认走 TCP、支持 rsync 式大块传输
  • root_squash 会把客户端 root 压制成 nobody,root 写 root 属主目录会 Permission denied,需用普通用户或调整属主
  • 开机自动挂载需在 /etc/fstab_netdev 选项,避免网络未就绪时报错

为什么需要 NFS

在集群、内网多机或虚拟化环境里,经常遇到"同一份文件要同时被多台机器读写"的需求:备份机要把数据推给存储机、多台 Web 服务器要共享同一份静态资源、开发机要直接编辑生产目录里的配置文件。逐台复制显然不现实,NFS(Network File System)就是为了解决这类问题而生的经典协议。

NFS 由 Sun 公司于 1984 年提出,经多代演进至今(RHEL 9 / Ubuntu 24.04 默认已是 NFSv4),把"远程目录"变成"本地目录",客户端使用起来和本地文件系统几乎没有差别。相比 Samba(SMB/CIFS),NFS 更贴近 Unix 原生语义,权限模型直接映射 Linux 的 UID/GID,性能也更好,是 Linux 之间共享文件的主流选择。

NFS 的工作原理

NFS 基于 RPC(Remote Procedure Call)实现,核心角色有两个:

  • NFS 服务端:持有真实数据,通过 /etc/exports 声明"把哪个目录共享给谁",并由内核的 nfsd 进程响应客户端请求
  • NFS 客户端:通过 mount -t nfs 把远程目录挂载到本地挂载点,之后所有文件操作都被内核翻译成 RPC 调用发给服务端

NFSv4 相比早期版本取消了 portmap 等一堆辅助服务的依赖,改用单一端口(默认 TCP 2049),防火墙配置更简单;现代内核(如 Ubuntu 24.04 的 6.8)默认协商到 vers=4.2

服务端:安装与导出

安装 nfs-kernel-server

Ubuntu/Debian 上服务端和客户端可以一起安装:

apt update
apt install -y nfs-kernel-server nfs-common

安装完成后服务端守护进程 nfs-server 会自动启动并设为开机自启:

systemctl status nfs-server --no-pager

创建共享目录

准备一个真实存放数据的目录,并在其中放一个测试文件,方便后续验证挂载后的读取:

mkdir -p /srv/nfs/share
echo '你好,NFS 共享测试文件' > /srv/nfs/share/welcome.txt

编辑 /etc/exports

共享哪些目录、允许哪些主机访问、以什么权限访问,全部由 /etc/exports 决定。每一行的格式是:

<导出目录> <允许的主机>(<选项>)

典型配置如下——允许 192.168.5.0/24 网段读写(局域网内所有机器),同时允许本机 127.0.0.1 挂载用于测试:

/srv/nfs/share 192.168.5.0/24(rw,sync) 127.0.0.1(rw,sync)

常用选项说明:

  • rw:可读写(默认是 ro 只读)
  • ro:只读
  • sync:服务端同步写盘后再应答,数据更安全(默认)
  • async:异步写盘,性能好但断电可能丢数据
  • no_subtree_check:关闭子树检查,现代版本默认行为,可以省略
  • root_squash:把客户端 root 映射为匿名用户(默认开启,详见下文)
  • no_root_squash:允许客户端 root 以 root 身份写(有安全风险,一般不推荐

应用导出并验证

改完 /etc/exports 需要重新应用,用 exportfs -ra 让配置生效(-r 重新导出,-a 导出所有):

exportfs -ra
exportfs -v
showmount -e localhost
  • exportfs -v 显示当前生效的导出及详细选项
  • showmount -e <服务端> 从"客户端视角"列出服务端开放了哪些共享

在本机上的实际输出:

导出配置与验证

可以看到 /srv/nfs/share 已对 192.168.5.0/24127.0.0.1 两个来源导出,选项里有 rwsyncroot_squash 等默认值。

客户端:挂载与读写

创建挂载点并挂载

在客户端机器(或本机)创建挂载点,然后用 mount -t nfs 挂载:

mkdir -p /mnt/nfs
mount -t nfs 127.0.0.1:/srv/nfs/share /mnt/nfs

服务端地址和目录用 服务端IP:/导出目录 的形式。挂载后查看挂载信息,确认协议与传输参数:

mount | grep 127.0.0.1:

输出类似(Ubuntu 24.04 内核默认协商到 NFSv4.2):

127.0.0.1:/srv/nfs/share on /mnt/nfs type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,...)

读取测试

挂载成功后,直接读取之前服务端准备的测试文件:

cat /mnt/nfs/welcome.txt

能读出 你好,NFS 共享测试文件,说明网络文件系统已正常工作。

root_squash:为什么 root 写不进去

接着上面的实验,在挂载点里尝试写入一个文件:

echo test > /mnt/nfs/root-test.txt

结果大概率是:

bash: line 1: /mnt/nfs/root-test.txt: Permission denied

这正是 NFS 默认的 root_squash 机制在起作用:出于安全考虑,服务端会把"来自客户端的 root"映射成一个没有任何特权的匿名用户(nobody),于是客户端 root 在共享目录里就变成了普通用户——如果目录属主是 root 且没有其他人写权限,自然写不进去。

整体实验过程:

客户端挂载、读取与 root 写入失败

cat 能正常读出文件(读权限不受影响),而写入报 Permission denied,退出码 1。

正确姿势:用普通用户写入

把共享目录的属主交给一个普通用户,客户端以该用户身份写入即可成功。先在服务端创建用户并调整属主:

useradd -m -s /bin/bash nfsuser
chown -R nfsuser:nfsuser /srv/nfs/share

然后在客户端以 nfsuser 身份通过挂载点写入:

su - nfsuser -c "echo 'NFS 客户端写入成功' > /mnt/nfs/client-write.txt"
ls -l /srv/nfs/share
df -h /mnt/nfs | tail -1

结果写入成功,服务端目录里能看到 nfsuser 属主的新文件,df -h 也能看到挂载在 /mnt/nfs 上的网络磁盘:

普通用户通过 NFS 写入成功并确认

关于 no_root_squash

如果确实需要客户端 root 直接以 root 身份操作共享目录,可以在 /etc/exports 对应条目加上 no_root_squash 后重新 exportfs -ra。但这样一来,任何能访问该共享的机器拿到 root 权限就等于拿到服务端目录的完整控制权,风险极高,仅建议在完全可信的专用内网使用。

开机自动挂载

如果希望客户端每次开机自动挂载,把挂载项写进 /etc/fstab

127.0.0.1:/srv/nfs/share /mnt/nfs nfs rw,_netdev,vers=4 0 0

关键选项是 _netdev——告诉系统"这个设备依赖网络,等网络就绪后再挂载",否则开机时网络未初始化会导致挂载失败甚至阻塞启动。之后可用 mount -a 立即验证:

mount -a

常用管理与排错

# 查看本机所有 NFS 导出
exportfs -v

# 从客户端视角列出某台服务端的共享
showmount -e <服务端IP>

# 卸载网络文件系统
umount /mnt/nfs

# 查看 NFS 内核线程与统计
nfsstat

# 查看挂载到本机的 NFS 客户端连接
nfsiostat /mnt/nfs

排错优先级:先确认 systemctl status nfs-server 正常;再看 /etc/exports 语法(exportfs -ra 会给出明确报错);客户端 Permission denied 优先怀疑 root_squash 与目录属主;连不上则检查防火墙是否放行 TCP 2049 端口。

小结

NFS 把"共享目录"从一项高级技能变成了十几条命令就能搭好的基础设施:服务端用 /etc/exports 声明导出并 exportfs -ra 生效,客户端 mount -t nfs 一行挂载。实践中最容易踩的坑就是权限——root_squash 默认把客户端 root 压成普通用户,遇到 Permission denied 先检查属主和导出选项,而不是怀疑网络。掌握导出、挂载、权限、自动挂载这四步,就能在多机环境里顺畅地共享文件。

发表评论

暂无评论,快来抢沙发吧!