今天我升级了博客服务器(即本站服务器)的操作系统发行版。升级过程非常坎坷, 记录如下。
升级系统前需要进行apt update
和apt upgrade
对系统的软件包进行全面升级。在这一步中, 由于之前遗留的一些问题, 某些软件包升级(或旧软件包卸载)的时候某些脚本会执行失败。经过检索, 我注释了脚本中会出错的一行, 暂时把这个问题解决了。
然后, 即可使用do-release-upgrade
升级发行版。升级主要过程中非常顺畅, 但到最后有几个软件包安装时出现错误。然而, 我也不知道怎么办, 于是先重启了。至此, 业务中断。
等了一会儿, 发现服务器可以ping通, 但是连不上SSH。于是, 我登录VPS管理面板查看, 尝试进入远程console修复。经过查看, 似乎是一个网络时间同步的服务启动不起来, 导致整个系统启动流程卡在那里。等了一段时间, 但它一直在尝试。
多灾多难, 捣鼓了一会儿, 我的Chrome浏览器崩溃了, 关掉之后再也打不开了。这时, 我考虑重新安装它。于是, 我使用Edge去下载Chrome安装包, 没过一会儿, Egde也打不开了。经查看Windows的应用程序日志, 可以看到它们都报过BEX64的错误。此时, 我发现IE还是可以打开的, 于是使用IE下载了Chrome安装包, 然后安装了Chrome。安装后, 我发现还是无法打开。尝试重启, 我发现刚刚重启完的一段时间内, Chrome和Edge都可以打开, 过了这个时间窗口就都打不开了。这时我猜想是不是我的杀毒软件(某国产软件流氓软件)有兼容性问题, 并尝试卸载它。卸载完之后立即尝试, 发现Chrome和Edge都可以顺利打开了。至此, 我继续修服务器。
这时我想到可以进入恢复模式, 挂载系统盘, 然后取消上述服务的开机自动启动。经过操作, 服务器重启之后, 我可以连接SSH了, 下文的操作均使用SSH完成。
经过测试, 虽然SSH可以连接, 但是Web服务还无法访问。经过检查, 我发现是我自己编译的Nginx在升级的时候被覆盖掉了, 导致我的一些配置无法被识别。将我自己编译的Nginx换回去后, Nginx可以启动, Web服务恢复。至此, 部分业务恢复, 降级运行。
此时, 吃饭时间到了, 先去吃饭。
晚餐后, 我继续调试, 并且看到很多服务都启动失败了。经过查看日志, 我发现上述网络时间同步服务启动不起来的原因是找不到某个文件。搞不明白为什么的我此时尝试使用strace
记录上述服务的系统调用轨迹, 希望看看是哪里出了问题。然而, 我发现如果直接手动执行上述服务的程序, 则可以启动。我又通过修改配置文件, 让systemd启动服务的时候带上strace
。我这次发现, 上述服务是找不到D-Bus的socket文件。然而, 经过手动查看, 我确认对应的socket文件是存在的, 这也说明了为什么直接手动执行可以成功。结合之前看的上述服务的systemd配置信息, 我基本确定是某种沙箱机制使得这个服务访问不到上述socket文件。我将该服务的启动命令行换成了ls
来核实了这一点。值得注意的是, 在相同配置文件下的全新安装的系统中, 这些服务都是可以正常启动的。
经过魔改配置文件、关闭一些沙箱限制和实验, 我最终确认上述服务无法找到socket文件的原因为, 配置文件中开启了PrivateTmp, 这使得该服务看到的/tmp
目录和/var/tmp
一开始都是空的。并且, 不巧的是, /var/tmp
被符号链接至了socket文件所在的/run
目录, 因此该服务看到的/run
目录也是空的。全新安装的系统没有这个问题是因为, /var/tmp
不是符号链接。
将/var/tmp
符号链接删除并创建/var/tmp
目录, 上述服务和其他之前不能启动的服务都可以正常启动了。
修复其他一些小问题之后, 业务完美恢复运行。
最后, 值得一提的是, 这个VPS是在多年前就已经创建, 一步步从Ubuntu的precise、trusty、xenial、bionic升级到今天的focal, 可能有非常多的历史遗留问题。
需要研究开发一套Intelligent System Debugging工具