QVINTVS · SCRIBET

Minimales Debian-Paket

Eigentlich sollte man meinen, dass die Erstellung eines Debian-Pakets, das keinerlei Code zum Kompilieren enthält, sondern nur Skripte, einfach sein sollte. Meine einzige weitergehende Anforderung war, dass ich das ordentlich GPG-signieren wollte. Von wegen einfach.

Es mag blasphemisch klingen, aber man kann auch unter Arch Linux dpkg installieren (ist im AUR) und hat danach Zugriff auf dpkg-deb zum Bauen des Archivs. Das klingt zwar theoretisch toll, ist aber leider unpraktikabel, weil im Gegensatz zum wunderschön einfachen ArchLinux-Paketformat die Debian-Leute eine Unmasse an Hilfstools um ihr Paketformat herum aufgebaut haben. Ich habe zunächst ein paar Stunden damit verbracht, ganz im Arch Way einfach das Paketformat direkt zu schreiben und dann in dpkg-deb zu füttern — das ist absolut zwecklos. Zwar kann man damit Pakete bauen, die sogar installierbar sind, aber sie verstoßen gegen eine ganze Reihe der Debian-Maintainerrichtlinien und man müsste die MD5-Prüfsummen, Signaturdateien und weiß Gott was noch händisch anlegen. Das tut einfach nicht.

Damit scheidet die nette Idee, Debian-Pakete direkt auf ArchLinux zu bauen, auch schon aus. Denn all dieser Berg an Werkzeugen, die Debhelper sind dort nicht verfügbar. Alle kompilieren will man aber auch nicht:

$ ls /usr/bin | grep dh | wc -l
61

Ich weiß nicht, warum man zur Verwaltung eines Paketformats 61 verschiedene Werkzeuge benötigt. Gewiss hat aber jedes einzelne dieser Werkzeuge eine so immens wichtige Daseinsberechtigung, dass ein Aufräumen nicht mal im Entferntesten in Frage kommt. An dieser Stelle möchte ich darauf hinweisen, dass Arch Linux mit zwei Werkzeugen auskommt (pacman und makepkg), die zudem auch nur eine sehr übersichtliche Zahl an Kommandozeilenoptionen bieten und trotzdem alle Notwendigkeiten erfüllen.

Debootstrap

Nachdem also das Bauen unter ArchLinux direkt abgehakt ist, empfehle ich stattdessen debootstrap aus dem AUR zu installieren und ein Mini-Debian-Chroot zu erstellen:

# debootstap wheezy ./wheezy
# chroot ./wheezy /bin/bash
# apt-get update
# apt-get upgrade
# apt-get install locales
# dpkg-reconfigure locales
# dpkg-reconfigure tzdata
# apt-get install sudo build-essential debhelper fakeroot dh-make
# adduser unprivuser
# usermod -aG sudo unprivuser
# su - unprivuser

Damit ist man fertig, was die Aufsetzung des Chroots angeht.

Minimales Debian-Paket

Es wäre natürlich möglich, ein reines Binärpaket zu erstellen (erkenntlich daran, dass das Kontrollverzeichnis „DEBIAN“ (in Großbuchstaben) heißt). Das würde wie oben beschrieben sogar von Arch Linux aus und ohne die Debhelpers funktionieren, ist aber auf die Dauer zuviel Arbeit, wenn man die Debian-Policy einhalten will. Stattdessen beschäftige ich mich also damit, wie man ein Sourcepaket erstellt, das effektiv keines ist. Dafür erstellt man sich zunächst ein Verzeichnis:

$ mkdir mypackage
$ cd mypackage

Darin platziert man nun das Shellskript, das man gern paketieren möchte. Es ist nicht erforderlich, vereinfacht aber vermutlich die übersicht, direkt die FHS-Struktur zu wählen; ich platziere also folgendes Shellskript:

#!/bin/sh
echo "Ich bin ein Test"

in die Datei usr/bin/meintest und mache sie ausführbar:

$ chmod a+x usr/bin/meintest

Damit ist das zu paketierende Skript fertig. Jetzt wird das Steuerverzeichnis für die Debhelper, „debian“ (in Kleinbuchstaben), angelegt:

$ mkdir debian
$ cd debian

control

Die wichtigste Datei hier ist die Datei control und sie sieht so aus:

Source: mypackage
Section: misc
Priority: extra
Maintainer: Marvin Gülker <m-guelker@pegasus-alpha.eu>
Build-Depends: debhelper
Homepage: http://www.pegasus-alpha.eu

Package: mypackage
Architecture: all
Depends: ${misc:Depends}
Description: Ein Testpaket
 Das ist ein Testpaket.

Die einzelnen Felder werden nur teilweise im Ubuntuusers-Wiki, ansonsten leicht angestaubt in der Debian-Policy von 1998 erklärt. Wie eigentlich ${misc:Depends} zustande kommt und warum man das immer einfügen soll, weiß ich immer noch nicht. Glückwunsch.

rules

Die nächste wichtige Datei ist rules. Das ist eine selbstausführende Makefile (!) mit folgendem Inhalt:

usr/bin/make -f
%:
        dh $@

Wirklich, das ist alles. Das ist eine Abkürzung durch die direkte Delegation aller Targets an das Programm dh; wer lieber die vollständige Makefile schreiben möchte, findet diese im Ubuntuusers-Wiki und sonst nirgendwo. Wehe den Paketierern, die kein Deutsch können und eine angepasste rules-Datei brauchen, wenn ihre Allmacht (siehe dh_auto_build(1)) mal das falsche macht.

$ chmod a+x rules

compat

Diese Datei enthält die Debian-Paketformatsversion, momentan einfach 8.

changelog

Dies ist vermutlich die Datei mit dem gewöhnungsbedürftigsten Dateiformat. Das ganze sieht so aus:

foobar (0.0.1-1) unstable; urgency=low

  * Erstmalig paketiert.

 -- Marvin Gülker <m-guelker@pegasus-alpha.eu>  Sat, 25 May 2013 12:10:20 +0200

Es ist darauf zu achten exakt die Anzahl an Leerzeichen zu verwenden, die ich hier benutzt habe. Das schließt das völlig unsinnige Doppelleerzeichen zwischen E-Mail und Datum mit ein. Bis auf das Datumsformat ist das Changelog-Format im UU-Wiki beschrieben; das Datumsformat finden wir wieder in der Policy von 1998. dpkg-buildpackage schlägt mit kryptischen Fehlermeldungen fehl, wenn man irgendwo ein Leerzeichen im Changelog falsch setzt.

Skripte

Es kann sehr praktisch sein, vor oder nach der Installation/Entfernung eines Pakets noch ein paar Setup/Cleanup-Skripte laufen zu lassen. Das UU-Wiki schweigt sich darüber aus, aber nach einer ordentlichen Volltext-Suche findet man einen passenden Abschnitt in der Policy. Ein Postinstall-Skript muss sich in der ausführbaren Datei postinst befinden und könnte so aussehen:

#!/bin/sh

case $1 in
    configure)
        echo "This is a post-install script"
        ;;
esac
$ chmod a+x postinst

Makefile

Ja, wir brauchen noch eine weitere Makefile. Da wir den Debhelpers irgendwie erzählen müssen, dass wir etwas bauen wollen, obwohl wir das gar nicht wollen, bzw. der Automagie von deb_auto_install irgendwie gerecht werden müssen, fügen wir unserem „Quellcode-Verzeichnis“ noch folgende normale Makefile hinzu:

$ cd ..
all:
        @echo "Nothing to build"

install:
        install -D usr/bin/meintest $(DESTDIR)/usr/bin/meintest

Diese Makefile wird während des Bauprozesses von dh (ihr erinnert euch an die rules-Datei?) zweimal verwendet: Einmal ohne Argumente, um den Quellcode zu bauen (da gebe ich einfach nur „Nothing to build“ aus) und einmal, um die kompilierten Programme in das zu packende Verzeichnis zu kopieren. Dieses befindet sich unter $(DESTDIR) wie man erkennen kann.

Gesamter Verzeichnisbaum

Hier nochmal der gesamte Verzeichnisbaum zur Kontrolle:

.
├── debian
│   ├── changelog
│   ├── compat
│   ├── control
│   ├── postinst
│   └── rules
├── Makefile
└── usr
    └── bin
        └── meintest

Paket bauen

Die Debhelpers für den Paketbau verlangen zwei Umgebungsvariablen, die wir ihnen nicht vorenthalten wollen:

$ export DEBFULLNAME="Marvin Gülker"
$ export DEBEMAIL="m-guelker@pegasus-alpha.eu"

Diese Informationen werden in die Paketmetadaten aufgenommen. Auch muss ein privater GPG-Schlüssel für die angegebene E-Mail-Adresse vorliegen.

Jetzt könnt ihr das Paket bauen:

$ dpkg-buildpackage -b

(-b baut ein Binärpaket). Ihr werdet nach eurer Passphrase gefragt und anschließend liegt das Paket sinnvollerweise im Verzeichnis über dem aktuellen Arbeitsverzeichnis.

Ich lobe mir das Paketformat von Arch Linux…

Update

Wie ich gerade eben noch herausgefunden habe (siehe hier), signieren die Debhelpers zwar bei dem Prozedere munter diverse Dateien, aber aus unverständlichen Gründen nicht das .deb-Archiv selbst. Das muss man händisch machen — dazu zunächst das notwendige zweiundsechzigste Hilfsprogramm installieren:

$ sudo apt-get install dpkg-sig

dann signieren (als “builder”, das ist wohl Konvention als Paketbauer)

$ dpkg-sig --sign builder mypackage_0.0.1-1_all.deb

Erst dann kann dpkg das Paket überhaupt verifizieren. Wer es händisch prüfen möchte:

$ dpkg-sig --verify mypackage_0.0.1-1_all.deb

Das sollte irgendwas mit “GOODSIG” am Anfang ausgeben.

Update2

Folgende Warnung lässt mich noch einmal hellhörig werden:

dpkg-source: Warnung: kein Quellformat in debian/source/format angegeben, lesen Sie dpkg-source(1)
dpkg-source: Information: Quellformat »1.0« wird verwendet
dpkg-source: Warnung: Quellverzeichnis »mypackage« lautet nicht <Quellpaket>-<UpstreamVersion> »mypackage-0.0.1«

Offensichtlich haben die einundsechzig Debhelpers immer noch nicht genug bekommen… Dem Ubuntuusers-Wiki lässt sich entnehmen, dass es die Formate „quilt“ und „native“ gibt — quilt funktioniert scheinbar nur mit vorhandenem Upstream-Tarball (jedenfalls bestanstanded dpkg-buildpackage dessen Fehlen), „native“ funktioniert jedoch scheinbar problemlos. Also noch zusätzlich die Datei debian/source/format mit folgendem Inhalt anlegen:

3.0 (native)

Valete.