Pacman/恢复本地数据库 - Arch Linux 中文维基

跳转到内容

# Pacman/恢复本地数据库

来自 Arch Linux 中文维基
< Pacman
翻译状态：

- 本文（或部分内容）译自 Pacman/Restore local database，最近一次同步于 2025-02-01，若英文版本有所更改，则您可以帮助同步与翻译更改的内容。
- 您可以在 ArchWiki 的对应页面找到本文翻译的原始修订历史。
- 本文可能与英文原文存在出入。

如果遇到下面的问题，很可能需要恢复 pacman 本地数据库：

- `pacman -Q` 什么都不输出，`pacman -Syu` 错误地报告系统已为最新。
- 使用 `pacman -S` 安装软件包时，很多已经安装过的依赖提示未安装。

pacman 储存本地软件包的数据库 `/var/lib/pacman/local` 很可能已经损坏甚至丢失。这是很严重的问题，请按照如下步骤修复。

首先，确认 pacman 的日志文件还在：

    $ ls /var/log/pacman.log

如果日志丢失了，那就不能使用本方法修复，可以尝试使用Xyne的软件包检测脚本重建数据库。要是还行不通，很遗憾，最后的路就是重装系统。

## 生成软件包恢复清单

警告：如果出于某些原因，您的 pacman 缓存或 makepkg package destination 包含了其他架构的包，请在继续前移除它们。

安装 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)

更新本地数据库以将不被其它包依赖的包标记为明确按照并将其它包标记为依赖。您将来在移除软件包时需要格外小心，但是原始数据库已丢失，这已经是我们所能做的最好的。

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

可选检查安装的软件包是否损坏：

    # pacman -Qk

可选参阅 Pacman/提示和技巧#查找不属于任何软件包的文件。

更新所有软件包：

    # pacman -Su

分类：​

- 包管理器

Pacman/恢复本地数据库
添加话题