解决APT包版本冲突与降级

近日,Ubuntu 16.04.x LTS可通过执行do-release-upgrade升级到18.04.1 LTS,故将一台VPS升级。

升级过程大体顺利,除了一些包的配置文件需要更新——我将diff输出的对比内容截图后保留(VNC Console中无法复制文本),并在系统更新完毕后将必要的行恢复到对应文件即可。


但升级后,我发现系统使用apt upgrade时无法升级g++和build-essential两个包(后者依赖前者,因而也无法升级)。

我首先尝试了网路上的方法——卸载重装,却发现卸载后无法重新安装,安装g++时出现了更多依赖错误,试图通过apt install安装每个有依赖错误的包,最终发现是gcc-8-base的版本问题。

此外,还有以下包也存在版本问题:

libatomic1
libgcc1
libgomp1
libitm1
liblsan0
libstdc++6
libtsan0

apt建议执行apt --fix-broken install,然而这完全不能解决问题。

gcc-8-base的版本号中存在8.1.0-5ubuntu1~16.04字样。检索后,发现是由ppa:ubuntu-toolchain-r/test提供的版本。回想起在这VPS运行Ubuntu 16.04.5期间,曾为使用新版本的gcc而添加了此第三方源。这个源提供的gcc-8-base没有被直接升级到Ubuntu 18.04.1所提供的版本,进而导致这些问题。

而gcc-8-base似乎是很多其他程序的依赖,尝试在apt中卸载它,会提示很多包也会被卸载,不仅包括自行安装的许多软件,甚至还包含libc6、dpkg和apt等,apt还要求输入Yes, do as I say!才能继续——无疑,这样做会损坏系统。

尝试使用apt install --reinstall gcc-8-base来重新安装,也不可行,出现'找不到对应版本'的提示——这似乎是因为第三方源提供的版本被apt认为版本号比官方源提供的更高

而使用apt-cache show gcc-8-base检索所有可用版本后,发现官方源所提供的版本号为8-20180414-1ubuntu2,试图用apt install --reinstall --allow-downgrade gcc-8-base=8-20180414-1ubuntu2来重新安装指定版本,却因为是降级操作,必须卸载再安装,遇到了相同的问题(会导致关键包被一并卸载,系统损坏)。

由此一来,便无法只通过apt来完成对gcc-8-base降级。

印象中使用dpkg -i安装一个已安装的deb包的历史版本,可以将其覆盖并完成降级。于是便做了如下尝试:

  1. 通过apt-cache show 包名查找每个有问题的包的官方源版本号
  2. 通过apt download 包名=版本号将deb包下载至一个目录
  3. 在此目录中通过dpkg -i *.deb来完成覆盖降级

这样做成功了。但要先降级gcc-8-base,再降级其它版本有问题的包,否则还是会出现依赖问题。

通过apt list --installed| less检索gcc-8-base版本,得到如下结果

gcc-8-base/bionic,now 8-20180414-1ubuntu2 amd64 [installed]

说明降级成功。再次尝试安装g++和build-essential,没有出现问题。