Normale Ansicht

Received yesterday — 25. Juli 2025

Wie dnf.8.gz in den Container kam

25. Juli 2025 um 06:42

Die folgende Geschichte soll mir zur Erinnerung und euch zur Unterhaltung dienen. Sie handelt von CentOS Stream 10, Containern und der Manpage dnf(8). Aber lest selbst.

Es war einmal ein Systemadministrator, der beim Training einige Subkommandos von dnf updateinfo kennenlernte, von deren Existenz er bislang nichts wusste. Und diese Subkommandos heißen list, info und summary. Neugierig schaute er in die Manpage dnf(8), doch zu seinem Erstaunen schwieg sich diese zu diesen Subkommandos aus.

Wut stieg in unserem Sysadmin auf. Wieder einmal haben sich die Entwickler keine Mühe gegeben, die Funktionalität ihrer Anwendung vernünftig zu dokumentieren. Die Qualitätssicherung hat geschlafen. So kann man doch nicht arbeiten. Doch nach dem ersten Wutanfall beschloss der Sysadmin, der Sache in Ruhe auf den Grund zu gehen, bevor er diesen Misstand anprangern würde.

Die Distribution des Sysadmins ist dafür bekannt, dass unter bestimmten Umständen Funktionalität von Upstream zurückportiert wird. Vielleicht hatte sich hier eine Diskrepanz eingeschlichen. Vielleicht war dieser Fehler in einer neueren Version ausgemerzt. Um dies schnell zu überprüfen, wollte unser Sysadmin einen Blick in dnf(8) in Centos 10 Stream werfen. Dazu führte er folgende Befehle in einer Kommandozeile aus:

$ podman run --rm -it centos:stream10
[root@01ede4521839 /]# man 8 dnf
bash: man: command not found
[root@01ede4521839 /]#

Mit einem Augenrollen erinnerte sich unser Sysadmin daran, dass Container-Images nur das absolut Notwendige enthalten, um möglichst wenig Speicherplatz auf der Festplatte zu belegen. Darüber, was absolut notwendig ist, werden seit anbeginn des Containerzeitalters philosophische Streitgespräche geführt. Also prüfte unser Sysadmin, ob es einen vertrauten Paketmanager gab, um die Manpages nachzuinstallieren:

[root@01ede4521839 /]# dnf in man-db man-pages
CentOS Stream 10 - BaseOS                       2.6 MB/s | 6.2 MB     00:02    
CentOS Stream 10 - AppStream                    1.5 MB/s | 2.4 MB     00:01    
CentOS Stream 10 - Extras packages              3.3 kB/s | 3.5 kB     00:01    
Dependencies resolved.
================================================================================
 Package             Architecture   Version                Repository      Size
================================================================================
Installing:
 man-db              x86_64         2.12.0-8.el10          baseos         1.3 M
 man-pages           noarch         6.06-3.el10            baseos         3.7 M
Installing dependencies:
 groff-base          x86_64         1.23.0-10.el10         baseos         1.1 M
 less                x86_64         661-3.el10             baseos         191 k
 libpipeline         x86_64         1.5.7-7.el10           baseos          53 k

Transaction Summary
================================================================================
Install  5 Packages

Total download size: 6.4 M
Installed size: 9.9 M
Is this ok [y/N]:
…
Installed:
  groff-base-1.23.0-10.el10.x86_64          less-661-3.el10.x86_64              
  libpipeline-1.5.7-7.el10.x86_64           man-db-2.12.0-8.el10.x86_64         
  man-pages-6.06-3.el10.noarch             

Complete!
[root@01ede4521839 /]# mandb
Processing manual pages under /usr/share/man...
Updating index cache for path `/usr/share/man/man7'. Wait...mandb: can't resolve man7/groff_man.7
mandb: warning: /usr/share/man/man7/man.7.gz: bad symlink or ROFF `.so' request
mandb: can't resolve man7/groff_man.7
mandb: warning: /usr/share/man/man7/man.man-pages.7.gz: bad symlink or ROFF `.so' request
Updating index cache for path `/usr/share/man/man3type'. Wait...done.
Checking for stray cats under /usr/share/man...
Checking for stray cats under /var/cache/man...
Processing manual pages under /usr/local/share/man...
Updating index cache for path `/usr/local/share/man/mann'. Wait...done.
Checking for stray cats under /usr/local/share/man...
Checking for stray cats under /var/cache/man/local...
45 man subdirectories contained newer manual pages.
2701 manual pages were added.
0 stray cats were added.
0 old database entries were purged.
[root@01ede4521839 /]# man 8 dnf
No manual entry for dnf in section 8

Resultat: Kein which-Befehl verfügbar. Diese Container-Image-Kuratöre sparten aber wirklich an allem. Doch der obige Codeblock enthüllt noch mehr. Zwar war der Paketmanager dnf installiert, auch die Manpages waren nun vorhanden, nur die Manpage dnf(8) fehlte immer noch. Und so bemühte der Sysadmin wieder die Tastatur, um zu prüfen, ob die entsprechende Datei tatsächlich fehlt, welches Paket sie bereitstellt und um das Problem zu lösen. Sehet und staunet:

[root@01ede4521839 /]# stat /usr/share/man/man8/dnf.8.gz
stat: cannot statx '/usr/share/man/man8/dnf.8.gz': No such file or directory
[root@01ede4521839 /]# dnf provides /usr/share/man/man8/dnf.8.gz
…    
dnf-4.20.0-9.el10.noarch : Package manager
Repo        : baseos
Matched from:
Filename    : /usr/share/man/man8/dnf.8.gz
[root@01ede4521839 /]# dnf reinstall dnf
Last metadata expiration check: 0:01:01 ago on Wed Jan  1 14:31:37 2025.
Dependencies resolved.
================================================================================
 Package       Architecture     Version                  Repository        Size
================================================================================
Reinstalling:
 dnf           noarch           4.20.0-9.el10            baseos           478 k

Transaction Summary
================================================================================

Total download size: 478 k
Installed size: 2.5 M
Is this ok [y/N]:y
…
Reinstalled:
  dnf-4.20.0-9.el10.noarch                                                      

Complete!
[root@01ede4521839 /]# stat /usr/share/man/man8/dnf.8.gz
  File: /usr/share/man/man8/dnf.8.gz -> dnf4.8.gz
  Size: 9         	Blocks: 8          IO Block: 4096   symbolic link
Device: 0,111	Inode: 6118189     Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-10-28 20:00:00.000000000 -0400
Modify: 2024-10-28 20:00:00.000000000 -0400
Change: 2025-01-01 14:32:59.692356995 -0500
 Birth: 2025-01-01 14:32:59.691356987 -0500

Überzeugt, dass der Spuk nun ein Ende habe, versuchte es unser Sysadmin erneut:

[root@01ede4521839 /]# man 8 dnf
No manual entry for dnf in section 8

Moment! Die Datei ist da, die Manpage jedoch nicht? Sind hier dunkle Mächte am Werke? Nein, denn wie die folgenden Befehle offenbarten, lag die Ursache lediglich in kaputten Symlinks und fehlenden Paketen:

[root@01ede4521839 /]# ls -l /usr/share/man/man8/dnf.8.gz
lrwxrwxrwx. 1 root root 9 Oct 28 20:00 /usr/share/man/man8/dnf.8.gz -> dnf4.8.gz
[root@01ede4521839 /]# ls -l /usr/share/man/man8/dnf4.8.gz
ls: cannot access '/usr/share/man/man8/dnf4.8.gz': No such file or directory
[root@01ede4521839 /]# dnf provides /usr/share/man/man8/dnf4.8.gz
Last metadata expiration check: 0:05:59 ago on Wed Jan  1 14:31:37 2025.
…
python3-dnf-4.20.0-9.el10.noarch : Python 3 interface to DNF
Repo        : baseos
Matched from:
Filename    : /usr/share/man/man8/dnf4.8.gz

[root@01ede4521839 /]# dnf list python3-dnf
Last metadata expiration check: 0:06:16 ago on Wed Jan  1 14:31:37 2025.
Installed Packages
python3-dnf.noarch                     4.20.0-9.el10                     @System

Getrieben von Ungeduld und etwas Frust installierte unser Sysadmin nun auch das Paket python3-dnf.noarch neu, in einem letzten, verzweifelten Versuch, endlich die lang ersehnte Manpage zu erhalten.

[root@01ede4521839 /]# dnf reinstall python3-dnf.noarch
…
Reinstalled:
  python3-dnf-4.20.0-9.el10.noarch                                              

Complete!
[root@01ede4521839 /]# man 8 dnf
DNF4(8)                               DNF                              DNF4(8)

NAME
       dnf4 - DNF Command Reference

SYNOPSIS
       dnf [options] <command> [<args>...]

DESCRIPTION
       DNF  is  the  next upcoming major version of YUM, a package manager for
       RPM-based Linux distributions. It roughly maintains  CLI  compatibility
       with YUM and defines a strict API for extensions and plugins.

Na endlich! Da war sie, die so lang ersehnte und schmerzlich vermisste Manpage. Und die Mühe unseres Sysadmins wurde mit der Erkenntnis belohnt, dass die gesuchte Information auch in dieser Version von dnf(8) nicht enthalten war. Zufrieden wandte sich der Sysadmin nun dem Ticketsystem zu, um zu erfragen, warum die gesuchten Informationen nicht vorhanden sind und um eine Ergänzung anzuregen.

Und wenn er nicht gestorben ist, wartet er noch immer auf eine Antwort.

Und die Moral von der Geschichte?

Erwarte nicht Manpages in Container-Images zu finden. Unser Sysadmin wäre deutlich schneller am ZIel angelangt, hätte er direkt in den Quelltext geschaut: https://github.com/rpm-software-management/dnf/blob/master/doc/command_ref.rst

❌