pacman/恢复本地数据库
外观
< Pacman
症状:输入/输出错误。
在以下情况下,可能需要恢复本地 pacman 数据库:
pacman -Q没有输出,而pacman -Syu却错误地报告系统已是最新状态。- 使用
pacman -S <package>安装软件包时,系统列出依赖关系已满足而没有继续安装。
这通常表明 /var/lib/pacman/local 损坏或被删除。
前提条件
检查 pacman 日志文件是否存在
$ ls /var/log/pacman.log
如果日志文件不存在,则无法使用此方法。替代方案:
- Xyne 的软件包检测脚本(可能有助于重建软件包列表)。
- 如果没有任何其他恢复手段,则需重新安装整个系统。
生成恢复列表
警告 在继续之前,请确保已删除来自其他架构的缓存软件包。
安装 pacman-contrib 以使用 paclog-pkglist。
创建恢复脚本
将以下脚本保存为 pacrecover 并使其可执行
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/。
执行恢复
定义一个辅助函数
recovery-pacman
recovery-pacman() {
pacman "$@" \
--log /dev/null \
--noscriptlet \
--dbonly \
--overwrite "*" \
--nodeps \
--needed
}
选项含义
--log /dev/null:避免污染日志。--needed:跳过已安装的软件包。--nodeps:允许安装依赖关系过时的缓存软件包。--dbonly,--overwrite "*",--noscriptlet:将 pacman 限制在仅重建数据库。
步骤
- 更新同步数据库
# pacman -Sy
- 安装本地可用软件包
# recovery-pacman -U $(< files.list)
- 从存储库安装剩余软件包
# recovery-pacman -S $(< pkglist)
- 重建显式/隐式安装状态
# pacman -D --asdeps $(pacman -Qq) # pacman -D --asexplicit $(pacman -Qtq)
- (可选)验证安装
# pacman -Qk
- (可选)识别无归属文件:参见 Pacman/技巧与窍门#识别不属于任何软件包的文件。
- 更新所有软件包
# pacman -Su