RPM

Der RPM Package Manager (wobei RPM ursprünglich „Red Hat Package Manager“ bedeutete) ist ein initial von Red Hat entwickeltes Paketverwaltungs-System. RPM bezeichnet das Paketformat an sich und alle nötigen Programme, um RPM-Pakete zu erstellen und verwalten. yum und dnf sind demnach erweiterte rpm-Tools, um RPM-Dateien aus RPM-Repositories (Datenbanken im weitesten Sinne) herunterzuladen, zu installieren und dabei Paket-Abhängkeiten aufzulösen.

Umgang mit RPM

Paket entfernen:

rpm --erase packagename

Paket nur aus der RPM-Datenbank entfernen:

rpm --erase --justdb packagename

Wer von rpm wissen möchte, ob ein Paket bereits installiert wurde, verwendet den Parameter --query:

rpm --query bridge-utils

Welche Dateien stecken in einem RPM-Paket?

rpm --query --list --package packagename.rpm

Prüfe die installierten Dateien gegen die ursprüngliche Spezifikation aus dem RPM-Paket:

rpm --verify openssh-server
SM5DLUGTP  c /etc/ssh/sshd_config
S.5....T.  c /etc/sysconfig/sshd
S file Size differs
M Mode differs (includes permissions and file type)
5 digest (formerly MD5 sum) differs
D Device major/minor number mismatch
L readLink(2) path mismatch
U User ownership differs
G Group ownership differs
T mTime differs
P caPabilities differ

c %config configuration file.
d %doc documentation file.
g %ghost file (i.e. the file contents are not included in the package payload).
l %license license file.
r %readme readme file.

Owner/Group und Permissions auf die ursprüngliche Spezifikation aus dem RPM-Paket zurücksetzen:

rpm --setugids openssh-server
rpm --setperms openssh-server

Wie extrahiert man die Dateien aus einem RPM, ohne sie zu installieren? Durch Umwandlung in ein .tgz- oder in ein cpio-Archiv, wobei erstes bevorzugt wird (rpm2archive ab RHEL 8, auf RHEL 7 nur rpm2cpio):

# get the rpm file
rpm2archive packagename.rpm; tar xvzf packagename.rpm.tgz
rpm2cpio packagename.rpm | cpio --extract --make-directories --preserve-modification-time --verbose

So zieht man die Sourcen eines Paketes, beispielsweise von Nano:

# RHEL 8+
dnf download --source nano
# RHEL 7
yumdownloader --source nano

rpm2archive nano-*.src.rpm
tar xvzf nano-*.src.rpm.tgz

Changelog zu einem Paket anschauen:

rpm --query --changelog curl

Wer wissen möchte, welche Dateien ein Paket mitliefert oder welche Abhängigkeiten es zieht, nutzt dnf repoquery (ab RHEL 8; auf RHEL 7 repoquery aus yum-utils):

dnf repoquery --list packagename
dnf repoquery --requires --resolve packagename

Alle installierten Pakete auflisten, die nicht von Red Hat, sondern von Drittanbietern stammen (der Vendor lautet auf RHEL Red Hat, Inc.):

rpm --query --all --queryformat '%{name} %{vendor}\n' | grep -v 'Red Hat'

rpmnew- und rpmsave-Dateien

Was ist der Unterschied zwischen einer *.rpmnew- und einer *.rpmsave-Datei?

Ein RPM-Paket markiert Konfigurationsdateien im SPEC mit %config oder %config(noreplace). Anhand dieser Markierung und der Frage, ob der Administrator die Datei seit der Installation verändert hat, entscheidet RPM bei einem Update, ob es die mitgelieferte Konfiguration einspielt oder die bestehende schützt. Ein ungewolltes Überschreiben angepasster Konfiguration wird so vermieden. Welche der beiden Dateien entsteht, hängt also von der Markierung ab, nicht vom Umfang der Änderung.

Nach jedem Update sollte nach diesen Dateien gesucht, der Inhalt untersucht und verglichen werden.

rpmnew - the packaged config, set aside (%config(noreplace))

Bei %config(noreplace) bleibt eine vom Administrator angepasste Datei aktiv und unverändert. Bringt das Update eine geänderte Version dieser Datei mit, wird diese als .rpmnew daneben abgelegt. Die Neuerungen müssen manuell untersucht und bei Bedarf in die aktive Datei übernommen werden, anschliessend kann die .rpmnew-Datei gelöscht werden. Hat der Administrator die Datei nie angefasst, wird sie kommentarlos durch die neue ersetzt.

rpmsave - the admin’s config, backed up (%config)

Bei einer nur mit %config (ohne noreplace) markierten Datei kommt die Version aus dem Update zum Zug. Hat der Administrator die Datei zuvor verändert, wird seine bisherige Version als .rpmsave gesichert. Solche Dateien bleiben auch bei der Deinstallation mancher Pakete (zum Beispiel chrony oder rsyslog) auf dem System liegen.

Um anzupassende Konfigurationsdateien zu finden und zu bearbeiten, gibt es zwei Wege: entweder find / -name '*.rpmnew' und anschliessend diff, mv, cp oder rm, oder rpmconf:

dnf install rpmconf
rpmconf --all
==> Package distributor has shipped an updated version.
  What would you like to do about it ?  Your options are:
   Y or I  : install the package maintainer's version
   N or O  : keep your currently-installed version
     D     : show the differences between the versions
     M     : merge configuration files
     Z     : background this process to examine the situation
     S     : skip this file

RPM-Epoche

Im Transaktions-Log (dnf history, Datei /var/log/dnf.log) steht vor manchen Paketnamen eine Zahl mit Doppelpunkt:

1:grub2-common-2.06-...
32:bind-license-9.16...

Die Zahl ist die RPM-Epoche (Default 0:). Sie überschreibt den normalen Versionsvergleich: Ein Paket mit höherer Epoche gilt immer als neuer, unabhängig von der eigentlichen Versionsnummer. Maintainer setzen eine Epoche grösser 0, wenn ein nach Versionsschema eigentlich älteres Paket trotzdem als Upgrade gelten soll.

Troubleshooting

The GPG keys listed for the "" repository are already installed but they are not correct for this package., Error: GPG check FAILED

Repo-Seite des Lieferanten besuchen und schauen, ob es eine Troubleshooting-Sektion gibt - meistens hat es seinen Grund, dass ein GPG-Key geändert wurde.

Oder:

dnf clean all
rm -rf /var/cache/dnf/*

# search for bad repo key
rpm --query gpg-pubkey --queryformat '%{name}-%{version}-%{release} --> %{summary}\n'

rpm --erase $BAD_REPO_KEY
rpm -vv --import https://example.com/path/to/GOOD_REPO_KEY
dnf repolist
Error in POSTIN scriptlet in rpm package, error: rpmdb: damaged header retrieved, error: cannot open Packages database in /var/lib/rpm

Das deutet auf eine korrupte RPM-Datenbank hin. Welches Datenbank-Backend im Einsatz ist, hängt von der RHEL-Version ab:

  • RHEL 8: Berkeley DB (/var/lib/rpm/Packages plus __db.*-Indexdateien)

  • RHEL 9 und 10: SQLite (/var/lib/rpm/rpmdb.sqlite)

Das aktive Backend zeigt rpm -E '%{_db_backend}'. Zuerst ein Backup ziehen und die Datenbank neu aufbauen lassen. Das funktioniert unabhängig vom Backend:

cp --archive /var/lib/rpm /tmp
rpm --rebuilddb
rpm --query --all > /dev/null   # test: shows errors only

Hilft das auf einem Berkeley-DB-System (RHEL 7/8) nicht, lassen sich die defekten Index- und Paketdateien manuell reparieren:

# RHEL 7/8 (Berkeley DB) only
rm /var/lib/rpm/__db*
/usr/lib/rpm/rpmdb_verify /var/lib/rpm/Packages
mv /var/lib/rpm/Packages /var/lib/rpm/Packages.broken
/usr/lib/rpm/rpmdb_dump /var/lib/rpm/Packages.broken | /usr/lib/rpm/rpmdb_load /var/lib/rpm/Packages
/usr/lib/rpm/rpmdb_verify /var/lib/rpm/Packages
rpm --rebuilddb

Bemerkung

/usr/lib/rpm/rpmdb_verify /var/lib/rpm/* funktioniert NICHT, Fehler werden so nicht erkannt. Auf SQLite-Systemen (RHEL 9/10) gibt es weder __db.* noch Packages; dort bleibt es bei rpm --rebuilddb oder der Wiederherstellung aus dem Backup.