两种配置解决同一个问题,却在相反的方向上失败。启动时挂载共享目录,会让每个服务得到一个文件系统——要么在里面,要么给出启动卡住的原因。按需自动挂载让机器快速启动,并把等待交给第一个触碰该路径的人。在 VPN 后面,后者通常是更划算的取舍,原因是隧道强加了一种启动顺序看不到的次序。

启动时挂载与自动挂载

启动时挂载很容易推理。文件系统目标会等待挂载,声明依赖它的服务随后启动,如果服务器不可达,机器要么等待,要么按选项直接失败。下游的一切都继承那一个决定。

自动挂载把这一切倒过来。路径立即存在,真正的挂载在某个东西打开它时才发生,而早启动的服务不会卡在尚未起来的隧道上。

比较归结为延迟该由谁吸收。需要在用户开始工作之前就拿到共享目录的工作站,大概应该等待。在包里启动的笔记本,或者共享可有可无的服务器,则不应该等。

两种做法都修不好缺失的路由。它们只是决定了失败在什么时候被观察到。

fstab 那一行,逐项来看

假设现有的 OpenVPN 客户端实例是 [email protected],服务器是 files.corp.example,挂载点是 /mnt/work。把这三处换成你自己站点授权的取值。一条可用的行长这样:

files.corp.example:/export/work /mnt/work nfs _netdev,nofail,x-systemd.automount,[email protected],x-systemd.mount-timeout=30s 0 0

_netdev 把挂载标记为需要网络,而它根本没有指名任何隧道。nofail 让共享目录对于常规文件系统目标保持可选。x-systemd.automount 创建按需触发器,而不是立即挂载。

x-systemd.requires= 是把挂载尝试绑定到 VPN 单元的那部分,它属于挂载操作,而不是触发器。把宽泛的顺序关系放在自动挂载单元自身上,正是人们制造循环、然后让 systemd 用没人会读第二遍的语言抱怨的方式。

x-systemd.mount-timeout=30s 限定的是最初那条挂载命令。它不限定之后发生的任何事,而这是关于这个选项最常见的误解。

“已启动”并不代表什么

查一下你命名的 VPN 单元上 active 意味着什么。隧道服务可能在到文件服务器的路由存在之前、或者在私有域名解析出来之前,就报告自己已经启动,此后再排顺序什么也换不来。几乎每一次失败的尝试都住在这道缝里。除非你去看路由和解析器而不是单元状态,否则它也是看不见的。

在存在的地方,把连接所有者自己的就绪信号当作附加前置条件。固定睡眠是一种猜测,在你的桌面上有效,在更慢的网络里或重连之后就会失败。

查看示例路径所生成的单元:mnt-work.automount 和 mnt-work.mount。在审阅过 fstab 改动之后,重新加载 systemd,并直接管理这些单元,而不是跑一条会波及无关条目的笼统 mount 命令。

这里还有一条提醒。启动时触碰 /mnt/work 的服务仍然会触发挂载,也仍然会等它,所以把共享标记为可选,并不会让每个应用都变得有耐心。

挂载之后是另一种失败

NFS 挂载完成之后,后续中断对一次读或一次写造成什么影响,由文件系统的重试与恢复行为决定。你设置的挂载超时对此没有任何影响。

软挂载会缩短某些等待并改变错误语义,还会带来数据完整性方面的后果,而这些在目标只是更快启动时很容易被忽略。为了抢两秒启动时间而选它,很少是划算的取舍。如果需求真的是中断期间的有界操作,那是应用层面的决定,而不是 fstab 标志。

决定隧道断开时,一个正在写入中途的进程该得到什么结果,并把它写下来。那个答案比任何选项字符串都有用。

要测四种状态,而不是一种

隧道可用时的正常启动是最容易的情况,几乎证明不了什么。它只确认那行字符串拼写正确,仅此而已。要测无 VPN 时的首次访问,再测它起来之后的恢复,最后测成功挂载之后一次受控的中断。

四种状态、四次观察,笔记就写在 fstab 条目旁边。下一个人继承的是行为,而不是一份还得自己反推的配置。

相关文章