Aus Linux-Magazin 02/2016

Was bei Debian- und Ubuntu-Paketen für Systemd zu beachten ist

© Theeraphan Satrakom, 123RF

Systemd betrifft nicht nur Admins von Systemen, sondern auch die Betreuer von Paketen. Ganz gleich, ob es sich um offizielle Distributionspakete oder das eigene Repository handelt – beim Umstieg auf Systemd gibt es einiges zu beachten.

Systemd [1] hat sich mittlerweile als Initsystem der Linux-Gegenwart etabliert. Und das trotz aller Widrigkeiten: Insbesondere das Debian-Projekt [2] musste diverse interne Diskussionen führen, bis sich die Debianer mittels einer Generalabstimmung auf einen Ersatz für das in die Jahre gekommene Sys-V-Init-System einigen konnten.

Andere Distributionen handelten in dieser Sache deutlich schneller: Fedora [3] liefert das maßgeblich von Lennart Poettering geschriebene Systemd seit 2010 aus und erhob es mit Version 15 zum Standard. Open Suse [4] zog mit der Ausgabe 12.1 nach. Über die Community-Distributionen landete Systemd schließlich auch in den jeweiligen Enterprise-Systemen der Hersteller. Dass Ubuntu [5] den Umstieg auf Systemd deutlich schneller absolvierte als seine Basisdistribution Debian, lag wohl auch daran, dass Mark Shuttleworth den Sieg von Systemd über die Konkurrenz öffentlich einräumte [6] und so die neue Marschrichtung für Ubuntu quasi von oben vorgab. Ein “Benevolent Dictator for Life” fehlt im Debian-Projekt – dem andernfalls wohl eine Vielzahl ermüdender Diskussionen [7] erspart geblieben wären.

Jessie war die erste Debian-Version mit einem funktionierenden Systemd an Bord. Viele Entwickler passen sich nun den neuen Begebenheiten an und kümmern sich um die Migration auf das neue Initsystem. Als integraler Systemdienst muss das insbesondere mit dem Paketsystem kooperieren: Installiert ein Admin ein Paket, das einen Daemon mitbringt, sollte dieser danach laufen.

Systemd mitdenken

Damit der Automatismus greift, müssen die Paketbetreuer ihre ».deb« -Pakete entsprechend vorbereiten. Bei Paketen im offiziellen Archiv von Debian oder Ubuntu haben das Debian-Projekt und Canonical ganze Arbeit geleistet: Nur noch wenige Pakete sind nicht kompatibel mit Systemd, für Ubuntu wartet eine Liste unter [8]. Admins dieser Systeme dürfen darauf vertrauen, dass sich die gelieferten Pakete in Sachen Initsystem so verhalten wie erwartet.

Viele Systeme nutzen jedoch nicht nur Pakete aus dem offiziellen Archiv. Das kann mehrere Gründe haben: Häufig bauen Admins eigene Pakete von Software, die noch nicht im Debian-Archiv steckt. Auch Unzufriedenheit mit den Paketen des Distributors kann ein Auslöser für den Eigenbau sein. In jedem Fall gilt: Wer selbst Pakete für seine Systeme pflegt, muss sie freilich auch von Sys-V-Init oder Upstart auf Systemd umstellen. Praktischerweise bringen sowohl Debian als auch Ubuntu viele Helferlein mit, die diverse Arbeitsschritte beim Paketbau automatisch erledigen. Die Paketbetreuer müssen die vorhandenen Werkzeuge im Wesentlichen miteinander kombinieren. Der Artikel zeigt, wie das für Debian- und Ubuntu-Systeme klappt.

Paket-Anatomie

Bei der Integration von Systemd-Ressourcen in Debian-Pakete ergeben sich nur marginale Unterschiede zwischen den Varianten für Debian und Ubuntu. Die grundsätzliche Herangehensweise ist gleich, Systemd hat die Unterschiede zwischen Debian- und Ubuntu-Paketen tatsächlich verkleinert. Für den weiteren Verlauf gilt, dass die Arbeitsschritte für Debian und Ubuntu identisch sind, wenn der Artikel nicht ausdrücklich etwas anderes angibt. Doch zunächst zur Anatomie eines Debian-Paketes, denn wer diese kennt, versteht auch die Arbeitsschritte beim Umrüsten auf Systemd besser.

Grundsätzlich entsteht ein Debian-Paket dadurch, dass ein Programmhersteller ein »debian« -Verzeichnis (Abbildung 1) in seinen Quelltext integriert. Das enthält alle Anweisungen für die Werkzeuge, die Debian für den Paketbau bereithält. Allen voran ist die »debhelper« -Toolsuite zu nennen. Im »debian« -Ordner liegt zudem stets eine Datei namens »rules« – kommt Debhelper zum Einsatz, ist sie inzwischen fast immer leer. Und es gibt weitere Dateien:

Abbildung 1: Neben den nötigen »changelog«, »control«, »copyright« und »rules« finden sich in »debian« oft viele weitere Dateien.

Abbildung 1: Neben den nötigen »changelog«, »control«, »copyright« und »rules« finden sich in »debian« oft viele weitere Dateien.

  • Das »control« -File enthält Informationen über die Binarypakete, die das jeweilige Quelltextpaket erstellt.
  • Die »changelog« -Datei merkt sich die Änderungen am Debian-Paket. Es ist im Normalfall nicht identisch mit dem Changelog für das vom Paket eigentlich verwaltete Programm.
  • In der Datei »copyright« vermerkt der Maintainer eines Debian-Paketes, welchen Lizenzen die einzelnen Dateien des Quelltext-Paketes besitzen.
  • In der Datei »format« im Unterordner »source« steht, welcher Version des Debian-Paketstandards das Quelltext-Paket unterliegt.
  • Kommt Debhelper zum Einsatz, legt zudem eine Datei namens »compat« einen Debhelper-Kompatibilitätslevel fest.

Die genannten sechs Dateien genügen bei einfachen Programmen in der Regel, um ein mit der Debian- oder Ubuntu-Policy kompatibles ».deb« -Paket zu erzeugen.

Systembefehle

Zusätzlich gibt es vier weitere wichtige Helfer, die im »debian« -Ordner häufig erstmal fehlen: Die Maintainer-Skripte.

Diese sind auf ein Binärpaket zugeschnitten, das aus einem Quelltextpaket entsteht, aus dem ein Entwickler grundsätzlich beliebig viele Binarys erzeugt. Bei nur einem Binary heißen die Maintainer-Skripte einfach »preinst« , »postinst« , »prerm« und »postrm« . Fallen aus einem Sourcepaket mehrere Binärpakete, nennen sich die Skripte dazu einfach »Paketname.preinst« , wobei Analoges für die drei anderen Skripte gilt. Ihre Namen verraten zugleich ihre Funktion: »preinst« führt vor dem Entpacken des Paketinhalts auf dem Zielsystem Befehle aus, »postinst« tut das nach dem Entpacken. Gleiches gilt für »prerm« und »postrm« , nur dass sie Pakete entfernen.

Dank dieser Skripte führen auch Programmpakete, die Upstart oder Sys-V-Init unterstützen, im Zuge der Installation Schritte aus, die das Initsystem auf dem Zielsystem einrichten. Sie rufen etwa auf Sys-V-Systemen mit Debian »update-rc.d« auf, um ein neues Initskript in den entsprechenden Runleveln in »/etc« zu verlinken.

Debhelper-Automatismen erschweren die Sicht

Der Teufel steckt allerdings im Detail: Die Maintainer-Skripte tauchen nämlich mitunter unverhofft im fertigen Debian-Paket auf, obwohl sie im »debian« -Ordner der entpackten Quellen fehlen. Denn Debhelper generiert sie automatisch, sobald das Werkzeug im »debian« -Ordner auf Dateien mit den Endungen ».upstart« oder ».init« stößt. Dann handelt es sich um klassische Sys-V-Initskripte oder um Upstart-Jobs, die im fertigen Paket in den Ordner »/etc/init« der paketinternen Dateistruktur gehören.

Das entsprechend Debhelper-Werkzeug, das dabei den Ton angibt, heißt »dh_installinit« . Es erkennt entsprechende Dateien in »debian« automatisch und kopiert sie im fertigen Paket an die richtige Stelle. Obendrein legt es »postinst« – und »prerm« -Skripte an, welche die nötigen Befehle für die Integration des Skripts oder des Upstart-Jobs enthalten.

Damit dieser Automatismus funktioniert, besitzen die Namen der Dateien in »debian« eine Bedeutung. Je nach Anzahl der Binärpakete, die aus dem Quellpaket purzeln, unterscheidet sich deren Name. Bei einem Binärpaket heißen sie »Dienstname.init« oder »Dienstname.upstart« . Im Fall eines Sourcepakets, das den Namens »gidentd« trägt, hieße das Skript in »/debian« nur »gidentd.init« . Produzierte das gleiche Sourcepaket hingegen ein zweites Binärpaket namens »gidentd-data« , würde der Name der Datei in »/debian« »gidentd.gidentd.init« lauten.

Wie passt Systemd in dieses Prinzip?

Die vorangegangene Beschreibung erklärt, wie sich Upstart-Jobs oder Sys-V-Initskripte in Debian-Pakete integrieren. Die gute Nachricht ist, dass sich im Hinblick auf Systemd-Dateien gar nicht so viel ändert, wie manche auf den ersten Blick vermuten. Denn letztlich unterscheidet sich die Integration von Systemd beispielsweise nicht so stark von der Upstart-Methode: Auch bei Systemd gibt es entsprechende beschreibende Dateien, die an eine spezifische Stelle im Dateisystem gehören, damit das Initsystem sie erkennt. Allerdings ist im Systemd-Sprech der Begriff Skript verpönt; stattdessen reden die Autoren von Unitfiles. Eine Gemeinsamkeit gibt es auch mit Skripten im Sys-V-Modell: Damit Systemd einen Job tatsächlich automatisch verwaltet und ihn beim Hoch- oder Runterfahren startet oder stoppt, muss der Dienst aktiviert sein. Das erledigt ein Befehl auf der Kommandozeile, der an das Sys-V-spezifische »update-rc.d« erinnert.

Die Systemd-Integration in Debian-Pakete muss also Elemente beider Welten vereinen, damit am Ende das gewünschte Resultat steht. Zum Glück haben die Entwickler Werkzeuge wie Debhelper bereits an Systemd angepasst. Komfortabel hat es also, wer ein Debian-Paket mit eigenem Systemd-Unitfile für die eigenen Server pflegt. Es zählt im Grunde nur eine Frage: Kommt die paketierte Software ab Werk mit einem eigenen Unit-File für Systemd, oder muss der Paketbetreuer selber eines schreiben? Davon hängt ab, wie leicht die Integration in Systemd gelingt.

Das Idealbeispiel: Ein Unit-file der Programmautoren

Auch bei den Autoren vieler Programme ist die frohe Botschaft von Lennart Poettering mittlerweile angekommen. Sie mögen Systemd, weil es Standard auf allen gängigen Linux-Distributionen ist. War es früher nötig, unterschiedliche Sys-V-Skripte für diverse Distributionen zu pflegen, existiert im Idealfall nur noch ein einziges Unitfile im Quelltext des Programms. In diesem gibt es lediglich eine Variable, die der Bauvorgang automatisch durch den kompletten Pfad zu eben jenen Dienst ersetzt, um den sich die Unitdatei kümmert. Sie eignet sich damit für praktisch alle Systeme.

Kein Wunder also, dass viele aktuelle Werkzeuge in ihren neuesten Versionen bereits Unitfiles für Systemd mitliefern. Der automatisierte Buildprozess mit Hilfe der Autotools bindet sie in der Regel ein. Der »make install« -Schritt installiert das jeweilige Unitfile automatisch mit. Stimmt der angegebene Präfix, landet es sogar direkt an der richtigen Stelle im Paket, so denn die erwähnten Autotools zum Einsatz kommen. Der Paketbetreuer muss bloß noch sicherstellen, dass das »postinst« -Skript das Unitfile wie gewünscht aktiviert.

Unitfiles mit Debhelper aktivieren

Wie das funktioniert, hängt wesentlich vom Automatisierungsgrad des jeweiligen Paketes ab. Unter Debian-Entwicklern hat es sich eingebürgert, im »rules« -Skript des Pakets ein Target für alle Aufrufe zu haben, das »dh« mit den entsprechenden Parametern startet. Ein typisches »rules« -Skript sieht so aus:

%:
        dh $@

Soll es dafür sorgen, dass »dh« Unitfiles für Systemd beachtet, genügt es, ans Ende des »dh« -Befehls den Parameter »–with systemd« zu hängen (Abbildung 2). Ist bereits ein »–with« -Parameter vorhanden, lässt sich das Keyword »systemd« an diesen anhängen, wobei ein Komma als Trenner zwischen dem letzten Buildflag und dem Eintrag für Systemd fungiert, also etwa:

Abbildung 2: Pakete, die in »rules« nur »dh« aufrufen, bekommen als zusätzlichen Parameter »--with systemd« mit auf den Weg.

Abbildung 2: Pakete, die in »rules« nur »dh« aufrufen, bekommen als zusätzlichen Parameter »–with systemd« mit auf den Weg.

%:
        dh $@ --with python2,systemd

Wer sein Paket für Ubuntu etwa auf Launchpad zur Verfügung stellt, lädt dort nicht die fertigen Binärpakete hoch, sondern lediglich das Sourcepaket. Launchpad kümmert sich mit seinen automatischen Builddaemons um den Rest. Damit der Vorgang funktioniert, muss das Paket die eigenen Build-Abhängigkeiten korrekt deklarieren. Sie betreffen jene Pakete, die während des Bauvorgangs installiert sein müssen, damit dieser funktioniert.

Die Debhelper-Erweiterung für Systemd kommt in einem eigenen Paket namens »dh-systemd« daher. Das Paket gehört nach dem Umstellen auf Unitfiles folglich in die Build-Dependencies eines Paketes für Systemd (Abbildung 3). Der passende Eintrag findet sich im »control« -File im »debian« -Unterverzeichnis im entpackten Quelltext des Pakets.

Abbildung 3: Die Debhelper-Integration von Systemd klappt nur, wenn »dh-systemd« zu den Build-Abhängigkeiten gehört.

Abbildung 3: Die Debhelper-Integration von Systemd klappt nur, wenn »dh-systemd« zu den Build-Abhängigkeiten gehört.

Das Paket bauen

Danach folgt der Aufruf von »dpkg-buildpackage« wie gewohnt. Will der Paketierer das Paket für Ubuntu über Launchpad verteilen, genügt der Parameter »-S« . Soll »dpkg-buildpackage« das Paket lokal bauen, benötigt es keine Parameter.

Ob das aus dem Bauvorgang resultierende ».deb« -Paket das Unitfile wie gewünscht enthält, lässt sich mittels »dpkg –contents« auf die ».deb« -Datei ermitteln: Im Idealfall findet der Entwickler das passende Unitfile für Systemd unter dem Pfad »./lib/systemd/system/Dienstname.service« (Abbildung 4). Der Erfolg einer Integration in die Maintainer-Skripte, lässt sich anschließend durch das Entpacken des Debian-Pakets herausfinden, zum Beispiel über den Befehl: »ar x gidentd_1.0-1_amd64.deb« . Die entstehende Datei »control.tar.gz« sollte eine »postinst« -Datei enthalten, in welcher sich eine Zeile wie

deb-systemd-helper enable Dienstname.service >/dev/null || true

findet. Falls ja, ist das Paket reif für die Produktion. Jedoch schadet es nicht, es mittels »lintian« noch auf seine Konformität mit der Debian-Policy zu überprüfen.

Abbildung 4: Wenn die Systemd-Integration wie vorgesehen funktioniert, findet sich im Paket am Ende des Vorgangs ein entsprechendes Unit-File in »/lib/systemd/system/«.

Abbildung 4: Wenn die Systemd-Integration wie vorgesehen funktioniert, findet sich im Paket am Ende des Vorgangs ein entsprechendes Unit-File in »/lib/systemd/system/«.

Weniger ideal: Unitfiles selber schreiben

Bisweilen kommt es vor, dass die Autoren von Programmen nicht darüber nachdenken, wie sich ihr Dienst auf den Systemen der Anwender sinnvoll nutzen lässt. Für die Betreuer von Paketen bedeutet das Handarbeit, denn ein entsprechendes Unitfile ist separat zu verfassen. Canonical stellt im Wiki von Ubuntu eine Gegenüberstellung bereit, die sich an Paketbetreuer richtet, die im Verfassen von Upstart-Jobs Erfahrung haben [9]. Sie erklärt detailliert, welche Upstart-Direktive in Systemd welches Pendant hat.

Weniger rosig sieht es aus, wenn zwar ein Sys-V-Initskript existiert, aber kein Unit-file für Systemd: Zwar sollten Initskripte laut der Linux Standard Base (LSB, [10]) grundlegende Regeln beachten, tatsächlich kochen die Autoren solcher Skripte aber oft genug ihr ganz eigenes Süppchen. Wer nicht auf einem Sys-V-Skript aufbauen kann, muss zwangsläufig von vorn anfangen.

Immerhin: Unitfiles für Systemd sind nicht besonders komplex. Im besten Falle genügen wenige Zeilen: Drei Abschnitte namens »Unit« , »Service« und »Install« liefern Systemd sämtliche Informationen, die es braucht, um einen Dienst einzurichten. Unter »Unit« finden sich die Schlüsselworte »Description« für eine kurze Beschreibung des Dienstes und »Documentation« , das einen optionalen Verweis auf die Programmdokumentation ermöglicht.

»Service« enthält neben der Angabe des Typs (»Type« ) auch Angaben zur Laufzeitumgebung des Dienstes (»Environment« ), zu Kommandos, die das Installationsskript vor dem eigentlichen Befehl aufruft, sowie zum Programmbefehl selbst (»ExecStartPre« und »ExecStart« ). »Install« legt schließlich fest, wann Systemd die Unit startet und welche Abhängigkeiten zu anderen Unitfiles sie hat. Ein Basis-Unit-File ist mit diesen Angaben tatsächlich komplett.

An die richtige Stelle

Eine solche Datei platziert der Paketbetreuer im »debian« -Unterverzeichnis der entpackten Quellen des Programms. Die zuvor zitierten Namensregeln gelten auch für Systemd, denn das Tool, das sich um die korrekte Installation von Unitfiles für Systemd kümmert, betreut auch Sys-V-Skripte und Upstart-Jobs: »dh_installinit« . Upstart-Jobs erkennt es, wenn deren Dateinamen auf ».service« enden. Wieder gilt, dass im Falle eines Sourcepaketes, das mehrere Binaries erzeugt, der Name des Pakets sowie der Name des Dienstes im Dateinamen vorkommen müssen, also etwa »gidentd.gidentd.service« , wenn der Name des Zielpakets und der Name des Dienstes jeweils »gidentd« lauten.

Der Rest des Vorgangs funktioniert so, als käme das Unit-File direkt vom Anbieter des Programms: Hinter den »dh« -Aufruf in »debian/rules« gehört lediglich ein »–with systemd« , damit sich Debhelper automatisch um den Rest kümmert. Auch muss das Paket »dh-systemd« unbedingt in den Build-Dependencies der Datei »debian/control« stehen. Natürlich lässt sich auch in diesem Beispiel mittels »dpkg -L« oder dem Entpacken des ».deb« -Paketes durch »ar -x« herausfinden, ob die Integration wie erwartet funktioniert.

Ausnahmen in “rules”-Dateien

Gelegentlich kommt es vor, dass sich in »debian/rules« nicht nur der Aufruf für »dh« findet, sondern auch weitere Inhalte. Im günstigen Fall ergänzen separate Einträge lediglich die Arbeit von »dh« und überschreiben einzelne Teile (Targets) davon. Im schlimmsten Falle bekommen Admins es aber mit einer vollständig selbst geschriebenen »rules« -Datei zu tun. Dann ist es wichtig, einen kühlen Kopf zu bewahren: Auch »rules« -Dateien ohne »dh« nutzen in aller Regel die Werkzeuge der Debhelper-Suite. Die Datei listet dann lediglich die einzelnen Skripte direkt auf. In beiden Fällen lässt sich Support für Systemd nachrüsten. Variante 1 beschreibt den Fall, bei dem »rules« lediglich einzelne Targets überschreibt (Abbildung 5).

Abbildung 5: Das Target »dh_installinit« muss die passenden Befehle für Debhelper enthalten, falls es der Buildprozess manuell überschreibt.

Abbildung 5: Das Target »dh_installinit« muss die passenden Befehle für Debhelper enthalten, falls es der Buildprozess manuell überschreibt.

Zu erkennen ist das im Zweifelsfalle an vielen »Make« -Targets, deren Name mit »override« beginnt. Auf diese Weise bietet Debhelper nämlich für praktisch jedes eigene Target eine Möglichkeit für den Paketbetreuer, die normale Abfolge der Arbeitsschritte zu ändern. Wichtig ist, zu prüfen, ob ein Target mit dem Namen »override_dh_installinit« existiert. Ist das der Fall, braut das »rules« -Skript an dieser Stelle sein eigenes Süppchen. Eine generelle Aussage zur Adaption an Systemd lässt sich leider nicht treffen – denn die jeweiligen Befehle fallen nahezu beliebig aus. In solchen Situationen ist am Ende wichtig, dass das Skript innerhalb des »override_dh_installinit« -Targets die Befehle »dh_installinit« sowie »dh_systemd_enable« und »dh_systemd_start« aufruft. Ist das gegeben, sind die Debhelper-Skripte für Systemd an Bord.

Wenn “dh” ganz fehlt

Schließlich gibt es noch den Fall, in dem die »rules« -Datei den »dh« -Befehl gar nicht aufruft: Meistens handelt es sich dann um Skripte, die schon ein paar Jahre auf dem Buckel haben und womöglich schon lange verwaist sind. Wer sich mit solch einem Paket herumschlagen muss, stellt am besten sicher, dass die drei genannten Debhelper-Befehle in »debian/rules« innerhalb des »binary-arch« und des »binary-indep« -Targets vorhanden sind. In den allermeisten Fällen reicht das schon aus, um die korrekte Funktionalität der Systemd-Integration zu gewährleisten. (kki)

Infos

  1. Systemd: https://wiki.freedesktop.org/www/Software/systemd/
  2. Debian: https://www.debian.org
  3. Fedora: https://getfedora.org
  4. Open Suse: https://de.opensuse.org
  5. Ubuntu: http://www.ubuntu.com
  6. Mark Shuttleworth, “Losing graciously”: http://www.markshuttleworth.com/archives/1316
  7. Martin Loschwitz, “Verlorene Liebe”: Linux-Magazin, S. 26.
  8. Liste der noch zu konvertierenden Ubuntu-Pakete: http://people.canonical.com/~jhunt/systemd/packages-to-convert/
  9. Gegenüberstellung von Upstart und Systemd-Unitfiles: https://wiki.ubuntu.com/SystemdForUpstartUsers
  10. Linux Standard Base: http://www.linuxfoundation.org/collaborate/workgroups/lsb
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben