pacman/Restore local database
Signs that pacman needs a local database restoration:
pacman -Q
gives absolutely no output, andpacman -Syu
erroneously reports that the system is up to date.- When trying to install a package using
pacman -S package
, and it outputs a list of already satisfied dependencies.
Most likely, pacman's database of installed software, /var/lib/pacman/local
, has been corrupted or deleted. While this is a serious problem, it can be restored by following the instructions below.
Firstly, make sure pacman's log file is present:
$ ls /var/log/pacman.log
If it does not exist, it is not possible to continue with this method. You may be able to use Xyne's package detection script to recreate the database. If not, then the likely solution is to re-install the entire system.
Generating the package recovery list
Install the pacman-contrib package to get paclog-pkglist.
Create the log filter script and make it executable:
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
Run the script (optionally passing additional directories with packages as parameters):
$ paclog-pkglist /var/log/pacman.log | ./pacrecover >files.list 2>pkglist.orig
This way two files will be created: files.list
with package files, still present on machine and pkglist.orig
, packages from which should be downloaded. Later operation may result in mismatch between files of older versions of package, still present on machine, and files, found in new version. Such mismatches will have to be fixed manually.
Here is a way to automatically restrict second list to packages available in a repository:
$ { cat pkglist.orig; pacman -Slq; } | sort | uniq -d > pkglist
failed to initialise alpm library
, then check if /var/lib/pacman/local/ALPM_DB_VERSION
exists - if not, then run pacman-db-upgrade
as root followed by pacman -Sy
and then retry the previous command.Check if some important base packages are missing, and add them to the list:
$ comm -23 <({ echo base ; expac -l '\n' '%E' base; } | sort) pkglist.orig >> pkglist
Proceed once the contents of both lists are satisfactory, since they will be used to restore pacman's installed package database; /var/lib/pacman/local/
.
Performing the recovery
Define a bash function for recovery purposes:
recovery-pacman() { pacman "$@" \ --log /dev/null \ --noscriptlet \ --dbonly \ --overwrite "*" \ --nodeps \ --needed }
--log /dev/null
allows to avoid needless pollution of pacman log, --needed
will save some time by skipping packages, already present in database, --nodeps
will allow installation of cached packages, even if packages being installed depend on newer versions. Rest of options will allow pacman to operate without reading/writing filesystem.
Populate the sync database:
# pacman -Sy
Start database generation by installing locally available package files from files.list
:
# recovery-pacman -U $(< files.list)
Install the rest from 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