pacman/恢复本地数据库

来自 ArchWiki

pacman 需要恢复本地数据库的迹象

  • pacman -Q 完全没有输出,并且 pacman -Syu 错误地报告系统是最新的。
  • 当尝试使用 pacman -S package 安装软件包时,它输出了一个已满足依赖项的列表。

很可能,pacman 的已安装软件数据库 /var/lib/pacman/local 已损坏或删除。虽然这是一个严重的问题,但可以通过按照以下说明进行恢复。

首先,确保 pacman 的日志文件存在

$ ls /var/log/pacman.log

如果它不存在,则无法继续使用此方法。您或许可以使用 Xyne 的软件包检测脚本 来重建数据库。如果不是,那么可能的解决方案是重新安装整个系统。

生成软件包恢复列表

警告: 如果由于某种原因您的 pacman 缓存或 makepkg 软件包目标包含其他架构的软件包,请在继续之前删除它们。

安装 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,然后重试之前的命令

检查是否缺少一些重要的基础软件包,并将它们添加到列表中

$ 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)

更新本地数据库,以便将任何其他软件包都不需要的软件包标记为显式安装,而将其他的标记为依赖项。 将来在删除软件包时您需要格外小心,但是由于原始数据库已丢失,这是我们能做的最好的。

# pacman -D --asdeps $(pacman -Qq)
# pacman -D --asexplicit $(pacman -Qtq)

可选地检查所有已安装的软件包是否损坏

# pacman -Qk

可选地 Pacman/技巧和窍门#识别任何软件包都不拥有的文件

更新所有软件包

# pacman -Su