OpenVPN 启动了却什么都没输出:先检查 log-append
手动启动时的沉默并不是故障。读取已加载配置文件里的 log 和 log-append,再把日志文件及其时间戳与进程对应起来。
你在 shell 里带着配置文件启动 OpenVPN,终端却毫无输出地停在那里。没有横幅,没有报错,也没有提示符。直觉会认为启动失败了,于是你又启动一个副本,再启动一个,机器上最后留下好几个只配置了一半的实例。在这一切之前,先检查配置文件里是否已有指令把日志重定向到了别处。沉默是控制台的性质,不是进程的性质。
沉默有两种截然不同的解释
第一种是进程运行正常,正在写一个你没在看的文件。第二种是它立刻退出,错误就记在同一个文件里。
两者都会留下空白的终端,而一个问题能把它们分开:现在到底有没有进程,以及被要求写入的那个文件里有什么。先回答这个问题,再去动配置。为了看到输出而重新启动,正是两个实例开始争抢同一个隧道设备和同一个端口的原因,由此产生的错误和最初的问题毫无关系。
先找到指令,再找到进程。
ps -o pid,args= -C openvpn
grep -nE '^\s*(log|log-append|cd|daemon|verb)\b' /etc/openvpn/server/server.conf找到正在运行的进程所用的目标位置
读进程实际启动时使用的配置文件,而不是你编辑的那份。由服务管理的实例通常加载另一条路径,并在另一个工作目录里运行,所以相对文件名会解析到你意想不到的地方。
显式的 cd 指令会让这种区分更清晰,因为相对路径会随目录切换而移动。如果你继承了这份配置,文件可能待在一个现在没人会去找的位置。
把文件的修改时间和你启动的那一刻作对比。上周的日志只能说明上周的情况。然后读取那个有变化的文件的最后几行,把里面的内容当作你一直缺失的启动信息。
log 与 log-append:证据与抹除
log-append 会追加到文件里已有的内容之后。log 会打开文件写入并截断它,所以在两者之间切换可能删掉你正要读取的那次运行记录。
如果有人在调试时改过这条指令,之前的证据已经没了,文件大小会小得可疑。在对比两次运行并断定有东西变化之前,知道这一点很有用。要有意地删除日志,或者保留它,但要清楚自己做的是哪一种。刻意移除的证据比意外丢失的证据更容易推理。
两个选项都不会创建缺失的父目录,也都不会绕过文件系统权限或服务沙箱授予访问。配置里看起来正确的路径,仍可能对守护进程运行所用的账户不可写,这时守护进程可能还没来得及报告就失败了。在认定文件名是问题之前,先检查目录是否存在、属主是谁。
当服务包装器截获输出时
在 systemd 下,标准输出和错误会进入 journal,除非显式的文件指令优先;而厂商的包装器可能把它们截获到完全不同的地方。
这就是同一份配置从 shell 启动和从 unit 启动行为不同的原因。unit 的环境、工作目录和标准流都与你的交互式 shell 不同。相对路径可能在一个上下文里解析成功,在另一个上下文里却落不到任何地方。两者不一致时,要读 unit 定义,而不是配置文件。
对比两种启动安排,而不是断定其中一种坏了。读 unit 的命令行和环境,再读同一时间窗口的 journal。如果包装器把输出重定向到自己的文件,那个文件现在就是你的日志,OpenVPN 的指令对消息去了哪里已经无关紧要。
先能读到输出,再提高详细程度
在找到目标之前提高详细程度,只会在你没看的地方产生更多文本。
一旦知道输出落在哪里,中等详细程度就能显示配置正在被解析、连接正在被尝试。排查启动问题,二到三就够了。只有在失败属于协商细节时,更高的级别才值得,而且它们也会让文件迅速变大。
然后去读真正的错误。安静的终端并不能证明隧道有没有起来,文件里记录的那个失败才值得修复。