Aus Linux-Magazin 05/2014

Initsystem-Alternative

© mezzotint123rf, 123RF

Wem Sys-V-Init zu altbacken und Systemd zu übergriffig ist, der sollte ein paar Runden mit Runit drehen. Das Initsystem vereint Vorteile beider Welten miteinander, der Admin behält die Kontrolle.

Während eine Distribution nach der anderen zu Systemd wechselt, geraten bewährte Initsystem-Alternativen wie das zehn Jahre alte Runit [1] schnell in Vergessenheit. Kein Wunder: Systemd [2] gilt zurzeit als erfolgreichster Zehnkämpfer, weil es so viele Features in sich vereint. Es verwaltet die Control Groups (Cgroups), unterstützt D-Bus und Kernel-D-Bus, beherrscht Socket-Aktivierung und löst Console Kit ab – selbst eine grafische Konfigurationsoberfläche [3] darf nicht fehlen.

Obwohl der Anwender von einzelnen Features durchaus profitiert, wird er selten alle Möglichkeiten ausschöpfen. Wer zudem, dem aktuellen Trend folgend, mit Linux-Containern oder virtuellen Maschinen für einzelne Dienste hantiert, braucht womöglich nur die Kernfunktion eines guten Initsystems, also die Supervision von Prozessen.

Supervision

Zur Supervision gehört, dass ein Initsystem mit Prozess-ID 1 (PID) startet, um Dienste zu überwachen und im Falle eines Absturzes neu aufzurufen. Dazu muss es Signale zuverlässig zustellen und Prozesse beenden können.

Im Gegensatz zu Sys-V-Init startet Runit Dienste parallel und stellt sich gegen den traditionellen Ansatz, sie als Daemons in den Hintergrund zu verbannen. Auf diese Weise kann es sich von lästigen PID-Dateien und den damit verbundenen Unannehmlichkeiten verabschieden. Diese Dateien brauchte Sys-V-Init, um zu erahnen, ob und unter welcher Prozess-ID ein Prozess läuft. Die Methode erwies sich in der Praxis allerdings als anfällig für Race Conditions, nicht gelöschte PID-Dateien verursachen weitere Störungen.

Runits Struktur

Runit besteht aus mehreren aufeinander aufbauenden Komponenten. An unterster Stelle steht »runsv« , das einzelne Dienste startet und überwacht. Dabei helfen simple Shellskripte, die den jeweiligen Dienst (etwa »sshd« ) aufrufen. Stürzen das Shellskript und der mit ihm verbundene Dienst unvermittelt ab, startet »runsv« Letzteres neu. Ein zweites Shellskript kümmert sich bei Bedarf um das Logging und verwendet die Standardausgabe des ersten Skripts als Eingabe. Auch dieses Skript überwacht »runsv« .

An zweiter Stelle steht »runsvdir« : Wie der Name verrät, startet und überwacht es die »runsv« -Prozesse, für jeden Unterordner einen. Alternativ gibt der Admin einen Ordner an, in dem »runsvdir« nach Symlinks sucht, die auf die »runsv« -Verzeichnisse verweisen. Sie stehen typischerweise im Ordner »/service/« .

Der Admin ergänzt oder entfernt die zugehörigen Dienste, indem er die Symlinks modifiziert. Stirbt ein »runsv« -Prozess unerwartet, startet ihn »runsvdir« neu. Dem Überwachungsdienst entgeht auch nicht, wenn das »/service« -Verzeichnis plötzlich neue Unterordner anbietet oder alte fehlen. In diesem Fall startet respektive beendet er die zugehörigen »runsv« -Prozesse.

Die Hauptkomponente ist aber das »runit« -Programm selbst, das Linux mit PID 1 ausführt. Seine Aufgabe: Es fährt das System und seine Dienste hoch und wieder runter. Nach dem Start durchläuft »runit« drei Phasen (Stages):

  • In Stage 1 startet es ein grundlegendes Linux-System. Es mountet und prüft Dateisysteme, richtet Konsolen ein, setzt die Systemuhr und so weiter.
  • In Stage 2 befindet sich das System vom Start bis zum Ausschalten. Nur in dieser Phase nimmt es Signale (»CONT« , »INT« ) entgegen, in ihr startet gewöhnlich auch »runsvdir« .
  • Stage 3 kommt ins Spiel, wenn das System runterfährt. Darin hängt Runit Dateisysteme aus, speichert die Systemuhr und so weiter.

Interessant für Admins: Sie können bei Bedarf jede Komponente einzeln verwenden. Sinn ergibt das beim Einsatz von »runsvdir« , das nicht notwendigerweise mit der Prozess-ID 1 starten muss. So kann ein Systembetreuer Runit in Verbindung mit Sys-V-Init verwenden oder eine »runsvdir« -Instanz pro Benutzer als Dienst einsetzen. Auf diese Weise verwalten die User ihre Dienste selbst.

Neben den drei Hauptkomponenten »runsv« , »runsvdir« und »runit« gibt es noch diverse weitere Werkzeuge. Am wichtigsten ist »sv« , das Dienste verwaltet (Abbildung 1). Es kann sie starten, stoppen, Signale senden und natürlich den Status von Diensten abfragen.

Abbildung 1: Das Runit-Tool »sv« kann unter anderem den Status von Diensten abfragen.

Abbildung 1: Das Runit-Tool »sv« kann unter anderem den Status von Diensten abfragen.

Das Tool »chpst« führt Programme mit verändertem Prozessstatus aus. Mit ihm ersetzt ein Admin den ausführenden Nutzer oder passt die verwendeten Ressourcen über die »ulimit« -Settings an. Das Tool integriert sich auch gut in die zu den Diensten gehörenden Shellskripte.

Als letztes Helferlein sei »svlogd« erwähnt, das Logging samt Logrotation offeriert. Dazu liest es Daten von der Standardeingabe und schreibt sie in Logdateien. Es achtet auch darauf, dass Logdateien und Verzeichnisse eine festgelegte Maximalgröße nicht überschreiten.

Schlecht integriert

Die meisten Distributionen arbeiten mit einem bestimmten Initsystem. Bei Debian ist dies derzeit noch Sys-V-Init, bei Gentoo Open RC [4], bei Ubuntu Upstart [5] und bei vielen anderen Distributionen Systemd. Dies bedeutet unter anderem, dass der Paketmanager direkt mit dem Initsystem interagiert, indem er etwa Prozesse startet und stoppt.

Noch wichtiger aber ist, dass paketierte Programme Startskripte ausschließlich für das hauseigene Initsystem ausliefern – die sind aber meist nicht mit anderen Initsystemen kompatibel. Entscheidet sich ein Admin dazu, ein alternatives Initsystem wie Runit zu verwenden, muss er sich selbst um die Startskripte kümmern. In manchen Fällen gibt es vorgefertigte Sammlungen von Startskripten, etwa im Ignite-Projekt [6], das dem Admin dabei hilft, Runit unter Arch Linux zu verwenden. In den meisten Fällen muss er die Skripte aber selbst entwerfen.

Wer nun aber gleich an 100-zeilige Shellskriptmonster denkt, wie sie Sys-V-Init zum Teil mitbringt, liegt zum Glück falsch: Runits Shellskripte beanspruchen meist nur wenige Zeilen. Sie starten das besagte Programm, ohne es aber wie Sys-V-Init in den Hintergrund zu verbannen, da Runit ja die Supervision übernimmt. Listing 1 zeigt ein Beispielskript für den Webserver Nginx, Listing 2 ein etwas komplexeres Skript für den SSH-Dienst, das die Existenz eines bestimmten Ordners voraussetzt.

Listing 1

Nginx-Skript

01 #!/bin/sh
02 exec /usr/sbin/nginx -g 'daemon off;' 2>&1

Listing 2

Sshd-Skript

01 #!/bin/sh exec 2>&1
02 if [ ! -d /var/run/sshd ]; then mkdir /var/run/sshd
03 chmod 0755 /var/run/sshd fi
04 exec /usr/sbin/sshd -D -e

Etwas haariger wird es bei den Skripten, die sich um Stage 1 und Stage 3 kümmern. Sie erledigen in der Regel grundlegende Aufgaben während des Bootprozesses und sind häufig stark auf die verwendete Distribution zugeschnitten. Im Falle von Arch Linux beinhaltet das erwähnte Ignite-Projekt passende Skripte für diese Stages. Debianer und die Anhänger anderer Sys-V-Init-basierter Systeme greifen derzeit noch auf existierende Skripte für diese Phasen zurück. In allen anderen Fällen kommen Admins nicht darum herum, solche Skripte selbst zu schreiben: Das kann durchaus einige Zeit und Recherche erfordern.

Das Baukastenprinzip

Runit bringt zwar nur wenige Features mit, ist aber so modular und flexibel gestaltet (Abbildung 2), dass der Admin viele Features größerer Initsysteme ohne viel Aufwand nachbauen kann, etwa die Abhängigkeiten zwischen Diensten. Soll etwa der Bluetooth-Daemon erst nach D-Bus starten, muss der Admin keine spezielle Syntax einsetzen, sondern passt bei Runit einfach das Shellskript des jeweiligen Dienstes so an, dass es die Abhängigkeit berücksichtigt. Listing 3 zeigt ein entsprechendes Startskript, dank dem »bluetoothd« auf D-Bus wartet.

Listing 3

sv check

01 #!/bin/sh
02 sv check dbus || exit 1
03 exec bluetoothd -n -d 2>&1
Abbildung 2: Mit Htop lässt sich der Admin die laufenden Runit-Prozesse übersichtlich anzeigen.

Abbildung 2: Mit Htop lässt sich der Admin die laufenden Runit-Prozesse übersichtlich anzeigen.

Der Befehl »sv check dbus« überprüft den aktuellen Status von D-Bus. Läuft der Dienst noch nicht oder startet ihn das Skript nicht binnen der nächsten 7 Sekunden, beendet sich das Skript mit dem Exit-Status »1« . Runit versucht nun den Dienst erneut zu starten, und das Spiel beginnt von vorn. In Extremfällen führt das zu Endlosschleifen, der Admin muss Skripte nachjustieren.

Prozessmanagement

Ein Markenzeichen von Systemd ist die Integration von Cgroups. Während Runit nicht in jedem Fall erkennt, zu welchem Vaterprozess ein Kindprozess gehört, ermöglichen es Cgroups über Vererbung, diese Beziehungen im Detail zu verfolgen. Das stellt sicher, dass Systemd mit dem Dienst auch alle Kindprozesse beendet. Ist ein Admin auf dieses Verhalten angewiesen, darf er es für Runit in purem Shellskript nachbauen, wozu etwa 50 Zeilen Code nötig sind.

Fazit

Das Fehlen einer Integration von Runit in den Paketmanager lässt sich, je nach Perspektive, als Fluch oder Segen betrachten. Ersteres liegt näher, weil der Admin die Startskripte für neu installierter Dienste per Hand einrichten muss. Allerdings sollten administrierte Systeme im Idealfall keine Überraschungen bereithalten, was aber passieren kann, wenn ein frisch installierter Dienst wie Postfix automatisch startet. Runit spielt eher Admins in die Hände, die mehr Kontrolle über ihr System wollen.

Wer sich also statt eines Zehnkämpfers lieber einen anspruchslosen Mittelstreckenläufer wünscht, der auch noch einige Tricks beherrscht, sollte einen Blick auf Runit werfen. Das Initsystem erweist sich als leichtgewichtige, wartbare Lösung für spezielle Probleme.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 3 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