1. 为什么要在 Manjaro 上折腾 NFS 服务手里这台 Manjaro 用了快两年滚动更新一路跟下来桌面体验确实舒服但真正让我离不开它的原因是它作为一台“家庭数据中转站”的稳定性。家里三台设备——一台主力台式、一台旧笔记本改的影音机、还有一台常年挂着的迷你主机——之间要频繁倒腾文件。最初我用的是移动硬盘来回插拔后来换成局域网共享试过 SMB也试过 NFS最后长期留下来的方案是 NFS。原因很直接在纯 Linux 环境里NFS 的性能和权限模型是最贴合原生文件系统语义的。SMB 虽然跨平台兼容性好但在 Linux 与 Linux 之间传输大量小文件时元数据操作的开销明显更高而且权限映射那一层经常让人抓狂。NFS 不一样它直接把服务端的 UID/GID 带到客户端权限判断几乎和本地文件一样自然。对于我这种“三台机器同一个用户名、同一套目录结构”的场景NFS 几乎是零心智负担。这篇内容适合谁看如果你手上有一台跑 Manjaro 的机器想把它变成局域网里的文件服务器让其他 Linux 设备像访问本地目录一样访问它那这篇就是写给你的。我会从零开始把服务端配置、客户端挂载、权限调优、开机自启、故障排查整条链路讲透包括我踩过的那些坑。整个过程不需要你懂什么高深的内核知识只要会敲命令、会改配置文件就行。需要提前说明的是NFS 的设计前提是“可信局域网”。它本身没有强认证机制早期版本甚至靠 IP 加主机名做信任。所以这套方案只适合你完全掌控的家庭网络或实验室内网绝对不要把它暴露到公网。这一点我在后面还会反复强调。2. 整体方案设计与核心思路拆解2.1 为什么选 NFS 而不是 SMB 或其它方案先把选型这件事说清楚因为很多人一上来就问“为什么不用 SMB”。我做过对比测试在同样的千兆内网、同样的机械硬盘条件下传输一个包含两万个小文件的源码目录NFSv4 比 SMB 快了大约三成。差距主要来自协议开销SMB 每个操作都要走一遍复杂的协商和签名流程而 NFS 的 RPC 调用轻量得多。另一个关键点是权限。SMB 默认走的是“用户映射”那一套服务端和客户端的用户需要额外配置对应关系稍不注意就变成 nobody 或者权限拒绝。NFS 直接把数字 UID/GID 传过去只要两端用户名对应的 UID 一致权限就是通的。我在三台机器上都用同一个 UID1000所以从来没为权限头疼过。至于为什么不选更“现代”的方案比如各种分布式文件系统或者同步工具那些东西要么太重要么是“同步”而非“共享”。我要的是“一份数据、多处访问、实时一致”NFS 正好卡在这个需求点上。2.2 Manjaro 上跑 NFS 的版本选择NFS 有几个版本v3 和 v4 是主流。我的建议是直接用NFSv4理由有三条。第一v4 只需要开放一个端口默认 2049而 v3 需要 rpcbind 加上一堆动态端口防火墙配置起来很烦。第二v4 原生支持 ACL 和更完善的锁机制。第三v4 有“伪文件系统”的概念可以把多个导出目录挂在一个虚拟根下客户端看起来更整洁。不过 v4 也有个坑它的身份映射依赖idmapd如果配置不对客户端看到的文件属主会变成 nobody。这个我在后面排查章节会详细讲。2.3 目录规划与导出策略在动手之前先想清楚你要共享什么。我的做法是单独划一个目录树而不是直接把/home整个导出去。原因很简单导出范围越大权限失控的风险越高。我建的是/srv/nfs下面按用途分子目录/srv/nfs/media影音文件只读为主/srv/nfs/share公共交换区读写/srv/nfs/backup备份落地区只有特定机器可写这种“一个根、多个子目录”的结构配合 NFSv4 的伪根客户端挂载时只需要挂一个地址就能看到所有子目录非常清爽。导出策略上我遵循“最小权限”原则能只读就不给读写能限定 IP 就不放开网段。具体配置在下一章展开。3. 服务端配置的完整实操3.1 安装必要的软件包Manjaro 基于 Arch包管理用 pacman。NFS 服务端需要两个包nfs-utils提供核心服务rpcbind在 v4 下其实不是必须的但某些工具链还会依赖它装上无妨。sudo pacman -Syu sudo pacman -S nfs-utils rpcbind这里有个细节pacman -Syu先做全系统更新是因为 Manjaro 是滚动发行版如果只装包不更新可能出现依赖版本不匹配。我遇到过好几次因为内核和 nfs-utils 版本错位导致服务起不来的情况养成先更新再装包的习惯能省很多事。装完之后用systemctl检查服务状态。注意NFSv4 主要靠nfs-server.service它会自动拉起需要的依赖。sudo systemctl enable --now nfs-server.serviceenable --now这个组合很实用既设置开机自启又立刻启动。启动后可以用systemctl status nfs-server确认看到 active (exited) 是正常的因为 NFS 服务本身是个“触发式”的服务它拉起内核模块后就退出了。3.2 编写 exports 配置文件核心配置文件是/etc/exports。这个文件的语法是“导出目录 客户端 选项”每行一条规则。我的配置长这样/srv/nfs 192.168.1.0/24(rw,sync,fsid0,no_subtree_check) /srv/nfs/media 192.168.1.0/24(ro,sync,no_subtree_check) /srv/nfs/share 192.168.1.0/24(rw,sync,no_subtree_check) /srv/nfs/backup 192.168.1.50(rw,sync,no_subtree_check)逐条解释这些选项因为这是最容易出错的地方。fsid0只加在根导出上它把/srv/nfs标记为 NFSv4 的伪根。客户端挂载时写server:/就能看到这个根而不是写完整路径。这是 v4 的特性v3 不需要。rw和ro不用多说读写和只读。sync表示数据先落盘再返回确认安全性高但性能略低对应的async性能好但断电可能丢数据。家庭场景我建议用sync因为丢数据的代价比那点性能损失大得多。no_subtree_check是个性能优化项。默认情况下 NFS 会检查请求的文件是否在导出的子树内这个检查在某些场景下会引发问题且拖慢速度。关掉它前提是你信任客户端不会乱来。192.168.1.0/24是网段写法表示整个子网可访问。如果你只想给单台机器就写完整 IP像 backup 那行一样。注意/etc/exports里绝对不能有行尾多余空格也不能用 Tab 和空格混排否则解析会出错。我因为这个排查了半小时。3.3 让配置生效并验证改完 exports 后不需要重启服务用exportfs命令重新加载即可sudo exportfs -ra-r是重新导出-a是全部。执行后用exportfs -v查看当前生效的导出列表确认选项和你写的一致。sudo exportfs -v输出里会列出每个目录、客户端和选项。如果某个目录没出现说明那行配置有问题回去检查语法。接下来验证服务端本地能否访问。装完 nfs-utils 后会有showmount工具showmount -e localhost正常的话会列出所有导出目录。如果报“clnt_create: RPC: Program not registered”说明 nfs-server 没起来回去看服务状态。3.4 防火墙放行Manjaro 默认可能没开防火墙但如果你开了ufw或firewalld需要放行 NFSv4 的端口。v4 主要用 2049但mountd和rpcbind在某些配置下还会用到其它端口。最省事的做法是直接放行整个内网网段sudo ufw allow from 192.168.1.0/24 to any port nfs如果你用的是 firewalld对应命令是sudo firewall-cmd --permanent --add-servicenfs sudo firewall-cmd --reload我个人的习惯是家庭内网直接关掉防火墙因为路由器那层已经做了 NAT 隔离。但如果你有访客网络或者不信任的设备在同一网段还是老老实实配防火墙。4. 客户端挂载与权限调优4.1 安装客户端工具并测试连通性客户端这边Manjaro 同样需要nfs-utilssudo pacman -S nfs-utils装完后先别急着挂载用showmount探一下服务端showmount -e 192.168.1.10把 IP 换成你服务端的实际地址。如果能看到导出列表说明网络和服务端都没问题。如果卡住或者超时先 ping 一下确认网络通再检查服务端防火墙。4.2 手动挂载验证第一次挂载建议手动来方便看报错。先建挂载点sudo mkdir -p /mnt/nfs然后挂载sudo mount -t nfs4 192.168.1.10:/ /mnt/nfs注意这里写的是:/因为服务端配了fsid0伪根。如果你用的是 v3要写完整路径:/srv/nfs。挂载后用df -h确认再ls /mnt/nfs看看能不能列出子目录。如果列出来但权限不对比如全是 nobody那就是 idmap 的问题下一节讲。4.3 权限映射与 UID 一致性NFSv4 默认启用 idmap服务端和客户端通过idmapd把用户名和 UID 做映射。如果两端用户名相同但 UID 不同就会出现权限错乱。最稳妥的做法是保证两端 UID 一致。在服务端和客户端分别执行id看输出里的 uid 是不是都是 1000。如果不是要么改一端的用户 UID要么在 idmapd 配置里做映射。改 UID 风险较大因为会影响本地文件属主所以我更推荐在新建用户时就规划好。如果确实需要映射编辑/etc/idmapd.conf把Domain设成一致的值比如localdomain然后重启nfs-idmapd.service。不过说实话家庭环境里统一 UID 是最省心的映射那套我试过坑不少。4.4 写入 fstab 实现开机自动挂载手动挂载没问题后就可以写进/etc/fstab了。我推荐用_netdev选项它告诉系统这是网络设备等网络就绪后再挂载避免开机时因为网络没起来而挂载失败。192.168.1.10:/ /mnt/nfs nfs4 _netdev,noauto,x-systemd.automount,x-systemd.idle-timeout60 0 0这里我用了x-systemd.automount它的好处是“按需挂载”只有真正访问/mnt/nfs时才建立连接闲置 60 秒后自动断开。对于不常访问的共享这个方案能省资源也能避免网络波动导致的挂载僵死。如果你希望开机就挂上把noauto去掉改成192.168.1.10:/ /mnt/nfs nfs4 _netdev,defaults 0 0改完 fstab 后用sudo mount -a测试没报错就说明配置正确。4.5 性能调优参数默认挂载参数在千兆网下够用但如果你追求更高吞吐可以加几个选项。我实测有效的组合是192.168.1.10:/ /mnt/nfs nfs4 _netdev,rsize1048576,wsize1048576,hard,timeo600,retrans2 0 0rsize和wsize是读写块大小默认可能只有 64K 或 128K调到 1M 能显著提升大文件传输速度。hard表示遇到服务端无响应时持续重试而不是报错退出适合稳定性优先的场景。timeo是超时时间单位是 0.1 秒retrans是重传次数。不过要注意rsize/wsize不是越大越好超过网络 MTU 和交换机缓冲能力反而会降速。我建议从 256K 开始试逐步往上调用dd或scp测速找到最佳值。5. 常见问题与排查技巧实录5.1 挂载报错 “access denied by server”这是最常见的错误原因通常有三个。第一客户端 IP 不在 exports 允许的范围内。检查服务端/etc/exports里的网段是否包含客户端实际 IP。第二exports 改了但没执行exportfs -ra。第三服务端防火墙拦了请求。排查顺序先在服务端showmount -e localhost确认导出正常再从客户端showmount -e 服务端IP确认能连上最后看防火墙日志。5.2 文件属主显示为 nobody前面提过这是 idmap 问题。先确认两端id输出的 UID 是否一致。如果一致还出问题检查/etc/idmapd.conf里的 Domain 是否两端相同。改完后重启nfs-idmapd和nfs-server。还有一个隐蔽原因服务端导出目录的父目录权限。NFS 在访问子目录时会检查路径上每一级的执行权限。如果/srv对其他人没有x权限客户端就会看到 nobody。用namei -l /srv/nfs/share可以逐级检查权限。5.3 写入速度慢或卡顿先排除网络问题用iperf3测一下两端带宽。如果带宽正常但 NFS 慢多半是sync选项导致的。可以临时改成async测试如果速度上来了说明是同步写入的开销。但如前所述我不建议长期用async。另一个原因是rsize/wsize太小。按上一节的方法调大试试。还有可能是服务端磁盘本身慢用hdparm -t测一下裸盘速度做对比。5.4 服务端重启后客户端挂载僵死这是 NFS 的经典问题。服务端一重启客户端的挂载点就变成“僵尸”任何访问都会卡住连df都能卡死终端。解决办法是挂载时加soft选项让超时后返回错误而不是无限等待。但soft有丢数据的风险所以更好的方案是用hard配合x-systemd.automount让 systemd 在服务端恢复后自动重连。如果已经卡死了用umount -f -l /mnt/nfs强制懒卸载然后重新挂载。5.5 常见问题速查表现象可能原因排查命令解决方向access deniedIP 不在允许范围showmount -e改 exports 并exportfs -ra属主 nobodyUID 不一致或 idmap 配置错id、cat /etc/idmapd.conf统一 UID 或改 Domain写入慢sync 或块大小小iperf3、dd调 rsize/wsize评估 async挂载僵死服务端重启mount、dmesg用 automount 或 soft 选项服务起不来包版本不匹配systemctl status nfs-server先pacman -Syu再重装5.6 几个我踩过的坑第一个坑是 exports 里的空格。有次我从网页复制配置行尾带了个不可见空格结果那条规则死活不生效exportfs -v里就是不显示。后来用cat -A才看出来。第二个坑是 SELinux。Manjaro 默认不开 SELinux但如果你从别的发行版迁移过来可能带着相关配置。NFS 导出目录需要正确的 SELinux 上下文否则会被拦。用getenforce确认状态如果是 Enforcing就得用semanage加规则。第三个坑是 IPv6。有次客户端解析服务端主机名时优先走了 IPv6但服务端只监听了 IPv4导致连接超时。解决办法是在 exports 里同时写 IPv4 和 IPv6 网段或者在客户端 fstab 里直接用 IPv4 地址。6. 进阶玩法与长期维护建议6.1 用 autofs 做更灵活的自动挂载systemd 的 automount 已经够用但如果你有多个共享目录、想按需挂载不同位置autofs更专业。它通过一个映射文件定义“访问哪个路径就挂哪个服务端”支持通配符和超时卸载。配置稍微复杂点但管理大量挂载点时优势明显。6.2 定期检查导出状态我写了个简单的脚本每周跑一次检查所有导出目录是否可访问、磁盘空间是否充足。核心就是exportfs -v加df -h输出到日志。这样能在问题变大之前发现苗头。6.3 备份策略NFS 共享的数据尤其是 backup 目录本身也需要备份。我的做法是在服务端用rsync定期把/srv/nfs同步到另一块物理盘。注意不要用 NFS 挂载来做备份源因为网络抖动会导致备份不完整直接在服务端本地操作最可靠。6.4 版本升级注意事项Manjaro 滚动更新时偶尔会遇到 nfs-utils 大版本升级导致配置格式变化。升级前先看 Arch 的新闻页升级后立刻exportfs -v确认导出正常。如果服务起不来journalctl -u nfs-server看日志多半是某个选项被废弃了。我个人在实际操作中的体会是NFS 这套东西“配一次、稳三年”前期把 UID、目录权限、exports 选项这三件事做对后面基本不用管。真正会出问题的往往是网络环境变化或者系统大版本升级。所以与其频繁折腾配置不如把排查命令练熟出问题时能快速定位。最后再分享一个小技巧把常用的showmount、exportfs -v、systemctl status nfs-server做成一个 alias 或者小脚本排查时一条命令全跑一遍比一条条敲快得多。