修复只在一个桌面上运行的 VPN 自启动项
某个桌面能启动、另一个桌面不能启动的 VPN 启动器是桌面项里的过滤规则,而不是隧道故障。先看 OnlyShowIn、TryExec 和覆盖文件。
VPN 客户端从应用菜单启动,隧道也连上了,但在一台机器上登录后图标始终不出现,而同一个软件包在另一台机器上却正常。三个观察被压成了一条抱怨:程序是否启动、界面是否可见、隧道是否建立。启动器由带有过滤键的桌面项控制,而那个桌面项与 VPN 协议毫无关系。按顺序走完这份手册,并在三者之一被干净地分离出来时停下。
三个彼此独立的事实:启动、图标、隧道
桌面项负责启动程序。它无法安装托盘实现,也无法让指示器出现在不支持该应用所用协议的顶栏里。如果进程已经在运行,那么启动问题已有答案,你面对的其实是集成问题。
隧道又是第三个事实。图标缺失并不能证明连接掉线,为了「修好」图标而杀掉并重启客户端,正是让一条正常隧道无故中断的做法。用户把图标缺失和隧道中断写在同一句抱怨里,这正是必须在纸面上把两者分开的原因。
在改动任何东西之前先把它们分开。先确认进程是否存在,再确认顶栏是否支持指示器,最后确认界面是否报告已连接。每个答案指向不同的层次和不同的负责人。
找到会话真正读取的那个文件
自启动项同时存在于用户目录和系统目录,文件名相同时用户副本优先。读错文件是改动看起来毫无效果的最常见原因。改任何东西之前先把两个目录都列出来,并记下会话实际会加载哪个文件。
ls -l ~/.config/autostart/ /etc/xdg/autostart/ echo "$XDG_CURRENT_DESKTOP" grep -H -E '^(OnlyShowIn|NotShowIn|TryExec|Hidden|Exec)=' ~/.config/autostart/*.desktop /etc/xdg/autostart/*.desktop
环境变量会打印过滤键所比对的会话名,通常是以冒号分隔的列表。要逐字与文件里的值比较,因为这些名字是区分大小写的配置细节,而不是对会话的描述。值GNOME与gnome并不匹配,由此产生的沉默不带任何错误信息。把它打印出来,而不是想当然。
如果两个目录里存在同名文件,起作用的是用户副本。改了系统文件却纳闷为什么毫无变化,是非常常见的一小时浪费。
按顺序读过滤键
下面的示例项展示了决定会话是否启动程序的几个键。它只是一个片段,不是完整的启动器,其中的值也属于虚构路径。
[Desktop Entry] Type=Application Name=Example VPN Exec=/opt/example-vpn/client --minimized TryExec=/opt/example-vpn/client OnlyShowIn=GNOME;
OnlyShowIn把该文件限制在列出的环境里,而NotShowIn则排除列出的环境。规范并没有定义两者同时出现时的有效行为,所以含有两者的文件应当视为缺陷,而不是什么聪明的组合。删掉不需要的那个键,而不是加上第二个再指望优先级规则。
TryExec会在会话启动它之前询问可执行文件是否存在。因此旧安装残留的路径会压制自启动,哪怕新软件包从菜单启动时完全正常,而这种故障看起来和桌面过滤一模一样。
在用户级别覆盖,而不是系统级别
当过滤规则对这台机器确实不合适时,把系统项复制到用户目录并修改副本。按照 XDG 自启动规则,同名的用户项优先,而Hidden=true可以在不删除系统文件的情况下停用它。
mkdir -p ~/.config/autostart cp /etc/xdg/autostart/example-vpn.desktop ~/.config/autostart/ sed -i '/^OnlyShowIn=/d' ~/.config/autostart/example-vpn.desktop desktop-file-validate ~/.config/autostart/example-vpn.desktop
退出登录之前先校验结果,因为格式错误的项会被静默忽略,下一次测试什么也说明不了。重装软件包不会移除你的覆盖文件,这正是重点,也是要记录它存在的原因。把文件路径写进工单,让下一个人直接找到覆盖文件,而不是重新推导一遍。
优先这样做,而不是去改共享的系统启动器:那会改变机器上每个用户的行为,而且无法以同样的方式复核。用户级覆盖只在一处可见,删掉一个文件即可回退,也容易在工单里解释。系统文件保持厂商发布时的样子,因此软件包更新不会悄悄推翻你的推理。
在不碰隧道的前提下确认启动
退出并重新登录,然后在看顶栏之前确认进程存在。成功启动和图标可见是两个不同的结果,只有后者才需要桌面集成方面的工作。把两者混为一谈,会让你去重装一个一直能用的软件包。
pgrep -af example-vpn systemctl --user status example-vpn.service journalctl --user -b --no-pager | grep -i example-vpn | tail -20
如果进程不存在,就重读那个文件,看是否还有残留的过滤键或过期的TryExec路径。如果存在,说明启动器正常,图标缺失是顶栏指示器支持的另一个问题,而不是你刚改过的那个文件的问题。
把三个观察记进工单:已启动、可见、已连接。这条记录能防止下一个人重复同样的三向混乱,也能说明哪一层还需要处理。