解决登录卡顿问题一例

ArchLinux,Gnome。有些时候,笔记本从睡眠中醒来,登录 Gnome,会卡好一阵子。经查是因为挂载了网络文件系统的缘故——比如休眠之前通过 gvfs 挂了个 samba,醒来重新登录的时候基本上要等一个超时才能见到桌面。

于是一直都是小心翼翼的在合上笔记本之前把该卸载的都卸载掉。但是这样人肉毕竟不方便。作为一个程序员,如果都不能给自己日常工作增加生产力,实在是羞耻。

于是准备用代码来解决问题。准备工作如下:
  • suspend 的 hook。翻了翻 wiki,现在什么 acpid、pm-utils 都不用了,hook 可以直接写成 systemd service file 的形式。
  • 卸载 fuser 的挂载。linux 的外围存储都是 sshfs 挂上来,在 mount 表里直接可以看到,最容易处理。
  • 卸掉 gvfs 的挂载。主要是来自 windows 的外围存储,Gnome 自带的 gvfs 其实还挺好用。但 gvfs 令人讨厌的是挂载行为变化不定,挂载点用 mount -l 是看不到的,之前还在 /run/user/$(id -u)/gvfs 下,而现在的版本则又找不到地方了。搜了一圈下来,看到 gio mount -s 可以直接按类型卸载,还算方便。
  • 干掉 vpn 进程。好几次休眠之前开着公司的 vpn,唤醒之后忘了,结果一边是 vpn 在顽强的尝试恢复连接,一边是我一头雾水在看为啥网络不通。
写好 suspend-root.service,实测发现以 root 用户身份执行的 gio mount -s 是有问题的,而且简单的用 su 或者 sudo 换掉身份也不行。gio 依赖 dbus,而 dbus 里面貌似也有 session 的概念,在开发环境即使用 root 都验证过了,放到 suspend hook 里还是会有问题,估计和 session 的生命周期有关,事情越搞越复杂。

好在后续的搜索工作找到了 xss-lock(其实最早 ArchLinux 的 wiki 上就提到过,但是被忽略了),可以越过 systemd 的 hook,让用户进程直接订阅 suspend 事件。于是又搞一个 user space 的 systemd service,用来卸载 gvfs 和 sshfs。

最终方案用到的脚本都在 github 的 toolbox 项目里了,用到的几个文件,分别是 suspend-root.servicexss-lock.service + umount_all。多说一点是 xss-lock 默认是会订阅包括屏保这样的事件的,所以 umount_all 里配合做了检查,只处理 suspend 的场景,我当然也不希望屏保和节电灭屏会破坏工作环境。

现在 Linux 桌面的各种机制也是越来越复杂了。

评论