如果遇到下面的问题,很可能需要恢复 pacman 本地数据库:
-
pacman -Q
什么都不输出,pacman -Syu
错误地报告系统已为最新。 - 使用
pacman -S
安装软件包时,很多已经安装过的依赖提示未安装。
pacman 储存本地软件包的数据库 /var/lib/pacman/local
很可能已经损坏甚至丢失。这是很严重的问题,请按照如下步骤修复。
首先,确认 pacman 的日志文件还在:
$ ls /var/log/pacman.log
如果日志丢失了,那就不能使用本方法修复,可以尝试使用Xyne的软件包检测脚本重建数据库。要是还行不通,很遗憾,最后的路就是重装系统。
生成软件包恢复清单
安装 pacman-contrib包 以获取 paclog-pkglist。
创建日志过滤脚本并使其可执行:
pacrecover
#!/bin/bash -e # load configuration settings from the makepkg configuration file . /etc/makepkg.conf # determine the cache directory from pacman configuration, defaulting to /var/cache/pacman/pkg, remove prefix with sed PKGCACHE=$( (grep -m 1 '^CacheDir' /etc/pacman.conf || echo 'CacheDir = /var/cache/pacman/pkg') | sed 's/CacheDir = //') # define directories to search for package files pkgdirs=("$@" "$PKGDEST" "$PKGCACHE") # read package name and version from input and construct a search pattern for package files while read -r -a parampart; do # loop through each directory to search for matching package files for pkgdir in "${pkgdirs[@]}"; do # check each file matching the pattern in the current directory for i in "$pkgdir"/"${parampart[0]}"-"${parampart[1]}"-*.pkg.tar.{xz,zst} ; do # if a file exists, print its path and stop checking further [ -f "${i}" ] && { echo "${i}" ; break; }; done # If no file is found, output the package name to stderr done || echo "${parampart[0]}" 1>&2 done
运行脚本(可选择将带有包的目录作为参数):
$ paclog-pkglist /var/log/pacman.log | ./pacrecover >files.list 2>pkglist.orig
这样做会创建两个文件:files.list
存储着依然在设备上的软件包的包文件;pkglist.orig
存储着需要下载的包。接下来的操作可能会导致设备上的旧版本包的部分文件与新版不匹配,需要手动干预。
过滤掉第二个列表中无法用软件仓库安装的包:
$ { cat pkglist.orig; pacman -Slq; } | sort | uniq -d > pkglist
failed to initialise alpm library
,请检查/var/lib/pacman/local/ALPM_DB_VERSION
是否存在。若不存在,请以 root 执行pacman-db-upgrade
,然后执行 pacman -Sy
,接下来重试之前的命令。检查是否缺失一些重要的 base 软件包并将它们加入列表:
$ comm -23 <({ echo base ; expac -l '\n' '%E' base; } | sort) pkglist.orig >> pkglist
如果两个列表的内容均就绪,无甚缺漏,就请继续下一步,它们将被用于恢复 pacman 的已安装软件包数据库 /var/lib/pacman/local/
。
开始恢复
为恢复工作定义一个 bash 函数。
recovery-pacman() { pacman "$@" \ --log /dev/null \ --noscriptlet \ --dbonly \ --overwrite "*" \ --nodeps \ --needed }
--log /dev/null
参数可以避免污染 pacman 日志;--needed
参数可以跳过数据库中已存在的包以节省时间;--nodeps
参数允许安装已缓存的包,即使已安装的包依赖于更新版本。其余选项用于使 pacman 在进行操作时不读写文件系统。
同步数据库:
# pacman -Sy
从 files.list
安装本地可用的包以开始生成数据库:
# recovery-pacman -U $(< files.list)
从 pkglist
安装其余包:
# recovery-pacman -S $(< pkglist)
Update the local database so that packages that are not required by any other package are marked as explicitly installed and the other as dependences. You will need to be extra careful in the future when removing packages, but with the original database lost, it is the best we can do.
# pacman -D --asdeps $(pacman -Qq) # pacman -D --asexplicit $(pacman -Qtq)
Optionally check all installed packages for corruption:
# pacman -Qk
Optionally Pacman/Tips and tricks#Identify files not owned by any package.
Update all packages:
# pacman -Su