OpenVPN 显示 active (exited)?找到你启动的那个实例
active (exited) 不是隧道,而是 RemainAfterExit 维持的一次性 /bin/true 任务。找到那个实例,读取它映射的文件,然后读它的日志。
你检查隧道,运行 systemctl status openvpn,得到没有 Main PID、进程列表为空的 active (exited)。最自然的读法是服务启动后又死了,于是你打开 unit,看到 /bin/true,断定软件包坏了。在 Debian 的打包里,这个状态正是按设计工作的 wrapper,隧道活在它启动的某个实例 unit 里。汇总 unit 永远不会告诉你是哪个实例建立了它。
这个 unit 上的 active (exited) 到底是什么
打包的 unit 是一次性任务:它的 ExecStart 是 /bin/true,而让已完成的 unit 仍被报告为 active (exited) 的正是 RemainAfterExit=yes。去掉这条指令,同样成功的 /bin/true 任务就会以 inactive (dead) 结束,而这恰恰是人们期待、又被反向误读的状态。该命令只是占位符,unit 报告的是其他 unit 所做的工作。这个安排里没有任何东西坏掉,替换 /bin/true 改变的是打包契约,而不是隧道。
wrapper 做的是转交。它启动软件包配置或其 systemd 生成器提供的各个实例 unit,所以空的进程列表并不能证明隧道不存在。没有选中任何实例时,wrapper 仍然成功,也仍然什么都不启动。这个状态回答的是 wrapper 有没有跑,而不是隧道在不在。
读 status 输出的三行,而不是括号里的那个词。Loaded 给出 systemd 读取的 unit 文件,Active 带有最后一次成功运行的时间戳,而缺失的 Main PID 与已结束的一次性任务相符。这三行也能把 wrapper 和启动一秒后就崩溃的服务区分开。
再读 status 之前,先列出 unit
先问 systemd 有什么,再问什么在运行。模板可能已安装,却一个实例都没实例化,只有被实例化的 unit 才承载隧道。从已加载的集合开始:
systemctl list-units 'openvpn*'
这份列表就是 systemd 此刻加载的内容,也是最接近隧道清单的东西。已安装的 unit 文件回答的是另一个问题,什么都没实例化时这份列表仍会显示模板:
systemctl list-unit-files 'openvpn*'
把两份列表放在一起读,因为第二份里的模板和第一份里的实例是两个不同答案。存在的模板和运行的实例不是同一件事,只有后者才意味着隧道。各发行版和 OpenVPN 版本的打包布局也不同。较旧的 openvpn@ 模板、拆分的 client 与 server 组合、发行版 wrapper,都可能在各自打包里成立。
按你自己的机器来,而不是照搬找到的教程。别人的输出里实例名可能是 office,你的是 home 或 work。真正可迁移的是方法,不是那个字符串。
顺着实例名找到它读取的文件
在上游 client 模板里,unit 的工作目录是 /etc/openvpn/client,命令从那里取 %i.conf,所以 openvpn-client@office 读的是 /etc/openvpn/client/office.conf。要在已安装的 unit 上确认这个映射,而不是相信示例,因为你手上的模板可能更旧,或被发行版改写过:
systemctl cat [email protected]
读那份输出底部的 drop-in,因为 .d/ 下的文件可以改 ExecStart、工作目录或配置路径。你以 office.ovpn 下载的配置文件并不是 实例打开的那个文件。这个落差正是错误指向一个你从未编辑过的路径的常见原因。
配置文件里的相对路径是下一个陷阱。移动主文件却让 ca、cert 和 key 引用保持相对,只是把缺文件错误换成另一个缺文件错误。第二个错误指向一个你确信存在的文件,所以配置目录比文件名更重要。
启动它,然后读那个实例的日志
启动你刚检查过的实例,因为汇总 unit 的日志里不会有隧道的错误。然后读这次启动的日志,按这个顺序找配置错误、文件访问错误和连接错误,因为它们各自在启动的不同阶段失败。
sudo systemctl start [email protected]
journalctl -u [email protected] -b
启动和启用是两个决定:start 现在运行 unit,enable 安排下次启动,enable --now 一步做完两件事。daemon-reload 重新读取 unit 定义,既不重启正在运行的进程,也不应用改过的配置。改完配置后要重启实例,因为那才是重新读取文件的操作。
不要在同一隧道上放第二个管理器
NetworkManager 和 OpenVPN 3 的会话管理器各自拥有连接状态,在它们之一的旁边再放一个 systemd 实例,就等于在同一隧道上有两个主人。症状是隧道起来后几秒就被替换,或者拒绝保持停止。选择发行版为桌面记录的管理器,在服务器上则有意使用 systemd。
启动实例前先检查是否已有主人。当桌面小程序显示连接时,你启动的实例是在和它竞争,而不是补全它。停用你不用的管理器,而不是两个都跑、指望顺序靠得住。这种冲突也解释了那些隧道建立后又被一个你从未启动的进程拆掉的日志。
用实例名、它读取的文件和失败的那行日志回答最初的问题。OpenVPN 关于 systemd 集成的说明 描述了模板布局以及实例名解析所经过的文件映射。