跳至內容
出自 Arch Linux 中文维基

如果遇到下面的問題,很可能需要恢復 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