Für das Starten von Systemdiensten ist das Init-System zuständig. Möchte der Admin es konfigurieren, begegnen ihm mittlerweile neben dem traditionellen System-V- und BSD-Init auch die modernen Upstart und Systemd. Eine Überlebenshilfe für die Praxis.
Die Anzahl der verfügbaren Linux-Distributionen ist immens – mehrere Hundert listet die Website Distrowatch auf. Diese Vielfalt sorgt dafür, dass jeder Anwender das spezielle Linux seiner Wahl findet. Dabei gab es lange trotz aller Unterschiedlichkeit eine gemeinsame Komponente: den Bootvorgang. Das System lädt und initialisiert den Kernel, entpackt eventuell eine Ramdisk und übergibt den weiteren Vorgang an das Programm Init. Es ist der Vater aller Prozesse, trägt die Prozess-ID 1 und startet direkt oder indirekt alle anderen Programme auf dem Linux-System.
Prinzipiell ist das heute immer noch so, aber am Ende der Ereigniskette steht nicht mehr notwendigerweise das altvertraute System-V- oder BSD-Init. Je nach Distribution begegnet der Linux-Anwender den neueren Lösungen Upstart oder Systemd. Sie erfordern vom Admin eine Portion Umdenken und Umlernen.
System-V-Init
Schon lange ist Init nicht mehr gleich Init. Auch wenn der Prozess stets »init« heißt, verbergen sich dahinter mehrere Varianten: die System-V- und die BSD-Implementierung. Beim System-V-Ansatz ist die Datei »/etc/inittab« der Dreh- und Angelpunkt. Hier legt der Admin fest, welche Prozesse der Init-Daemon beim Booten startet.
Ein wesentliches Merkmal des System-V-Init ist das Runlevel-Konzept. Der Linux-Anwender legt pro Runlevel fest, welche Prozesse Init starten oder stoppen soll. Man kann sagen, dass das Runlevel den Soll-Zustand des Betriebssystems charakterisiert. Bei System-V-Init stehen dem Admin zwei Möglichkeiten zur Verfügung, um einen Dienst unter die Kontrolle des Init-Daemon zu stellen. Der direkte Weg besteht darin, die Inittab anzupassen. Die allgemeine Syntax lautet:
ID:Runlevels:Aktion:Prozess
Die ID ist gewissermaßen ein Etikett für den Dienst und muss eindeutig sein. Auf alten Systemen sind hier maximal zwei Zeichen erlaubt, auf neueren sind vier möglich. Der nächste Punkt legt fest, in welchen Runlevels der Dienst laufen soll. Mit der Aktion legt der Anwender fest, wie Init den Dienst behandelt (siehe Tabelle 1). Der Eintrag »Prozess« spezifiziert schließlich die auszuführende Kommandozeile. Dieses Kommando startet Init beim Booten oder beim Neu-Einlesen der Konfiguration. Entfernt der Admin die Zeile wieder, stoppt der Init-Daemon den Prozess beim Neu-Einlesen seiner Konfigurationsdatei.
Init-Skripte
Das Verwalten von Diensten allein über die Inittab ist längst nicht mehr zeitgemäß. Das Runlevel-Konzept des System-V-Init erlaubt eine elegantere und auch besser automatisierbare Vorgehensweise. Pro Dienst existiert ein Shellskript im Verzeichnis »/etc/init.d/« . Das nicht ungefährliche Editieren der Konfigurationsdatei des Init-Daemon entfällt.
Wer ein Skript im Verzeichnis »/etc/init.d/« platziert, schafft zwar die Voraussetzungen für die Verwaltung durch Init, aktiviert diese aber nicht. Dazu fehlen die symbolischen Links in den entsprechenden Runlevel-Verzeichnissen »/etc/rcN.d/« . Dennoch kann der Admin das Skript über »/etc/init.d/myservice Aktion« testen. Gültige Aktionen sind in Tabelle 2 aufgelistet.
Aktionen
Die Aktionen »start« , »stop« , »restart« , »force-reload« und »status« sollten eigentlich alle Init-Skripte unterstützten – »reload« dagegen ist optional. Erfahrungsgemäß implementieren fast alle Skripte das Starten und Stoppen des Dienstes, danach trennt sich die Spreu vom Weizen. Schade, denn die Restart-Option zu implementieren ist ein Kinderspiel, wenn Starten und Stoppen funktionieren.
Zurück zum Anlegen der Symlinks in den Runlevel-Verzeichnissen: Im einfachsten Fall muss der Admin dies manuell tun. Er schafft Start-Links, deren Name mit S, und Kill-Links, deren Name mit K beginnt. Darauf folgen Nummern, die dem Init-System mitteilen, in welcher Reihenfolge die Links abzuarbeiten sind.
Leichter hat es der Admin, wenn er ein Linux-System vor sich hat, das den Anforderungen der Linux Standard Base (LSB) genügt. Diese Spezifikation schreibt vor, dass sich das Anlegen und Löschen der Symlinks auch mit dem Tool »insserv« erledigen lässt. Suse-Benutzer kennen dieses Kommando schon länger, aber inzwischen hat es auch in der Debian-Welt Einzug gehalten. Red-Hat-Freunde müssen eventuell einen anderen Weg gehen, doch dazu gleich mehr.
Damit die Automatisierung der Symlinks funktioniert, muss das Init-Skript einen festgelegten Header besitzen, der die notwendigen Informationen enthält (siehe Listing 1). Mit »insserv /etc/init.d/Dienst« registriert der Linux-Admin den Dienst beim Init-Daemon, das Kommando »insserv -r /etc/init.d/Dienst« meldet das Skript wieder ab. Sind die entsprechenden LSB-Konformitätspakete installiert, ist ein ähnliches Vorgehen auch bei Fedora oder Mandriva möglich. Gemäß der Spezifikation kann der Linux-User auch die Kommandos »/usr/lib/lsb/install_initd« und »/usr/lib/lsb/remove_initd« zum Registrieren oder Abmelden eines Init-Skripts verwenden.
Listing 1
LSB-kompatibler Header eines Init-Skripts
01 ### BEGIN INIT INFO 02 # Provides: boot_facility_1 [ boot_facility_2 ...] 03 # Required-Start: boot_facility_1 [ boot_facility_2 ...] 04 # Required-Stop: boot_facility_1 [ boot_facility_2 ...] 05 # Should-Start: boot_facility_1 [ boot_facility_2 ...] 06 # Should-Stop: boot_facility_1 [ boot_facility_2 ...] 07 # Default-Start: run_level_1 [ run_level_2 ...] 08 # Default-Stop: run_level_1 [ run_level_2 ...] 09 # Short-Description: short_description 10 # Description: multiline_description 11 ### END INIT INFO
Auf einer Red-Hat-kompatiblen Plattform gibt es aber noch eine andere Möglichkeit: das Tool »chkconfig« . Analog zu »insserv« erwartet das Kommando einen speziellen Header im Init-Skript, der die nötigen Information zum Anlegen oder Löschen der Runlevel-Symlinks enthält (siehe Listing 2). Der Befehl »chkconfig –add Dienst« meldet den Dienst beim Init-Daemon an, »chkconfig –del Dienst« entfernt die Symlinks. Neuere Versionen des Tools verstehen auch den LSB-Header und räumen diesen Angaben sogar höhere Priorität ein.
Listing 2
Angaben für chkconfig im System-V-init-Skript
01 # chkconfig: run_level_1[ run_level_2 ...] start_priority stop_priority 02 # description: short_description
Selbst eingerichtet
Als Beispiel für einen selbst eingerichteten Daemon soll ein Dienst namens »foobar« herhalten. Seine Merkmale sind in Tabelle 3 aufgelistet. Die direkte Verwaltung durch den Init-Daemon zeigt Abbildung 1 in Form einer interaktiven Terminalsitzung: Der Admin aktiviert den Dienst Foobar in »/etc/inittab« durch Entfernen des Kommentarzeichens. Der Init-Daemon erfährt durch das Kommando »telinit q« von dieser Änderung und startet den Service, der daraufhin in der Prozessliste auftaucht. Das Entfernen (oder Auskommentieren) des Dienstes Foobar deaktiviert ihn wieder, wobei der Init-Prozess den Foobar-Service erst nach der erneuten Eingabe von »telinit q« beendet.
Listing 3 zeigt ein – zugegeben recht einfaches – System-V-Init-Skript. Neben dem LSB-Header sind auch Informationen für »chkconfig« enthalten. Dabei ist das Skript nicht vollständig LSB-konform, denn es fehlt die Festlegung der Rückgabewerte, wie es der Standard eigentlich vorschreibt. Als Anschauung genügt es aber auch in dieser Form, weiterführende Infos findet der Leser in der LSB-Spezifikation für Init-Skripte unter [1].
Listing 3
Einfaches Init-Skript für den foobar-Dienst
01 #!/bin/sh 02 # 03 ### BEGIN INIT INFO 04 # Provides: foobar 05 # Required-Start: 06 # Should-Start: $syslog 07 # Required-Stop: 08 # Should-Stop: $syslog 09 # Default-Start: 3 5 10 # Default-Stop: 11 # Short-Description: foobar service 12 # Description: Start the foobar daemon for educational purposes 13 ### END INIT INFO 14 15 FOOBARBIN=/usr/sbin/foobar 16 MYRC=0 17 18 case "$1" in 19 start) 20 echo -n "Starting foobar service" 21 $FOOBARBIN -d || MYRC=1 22 ;; 23 stop) 24 echo -n "Stopping foobar service " 25 $FOOBARBIN -k || MYRC=1 26 ;; 27 restart) 28 $0 stop 29 $0 start 30 ;; 31 status) 32 ps -ef|grep [f]oobar > /dev/null 2>&1 33 if [ "$?" -eq 0 ]; then 34 echo "Service foobar is running" 35 else 36 echo "Service foobar is NOT running" 37 fi 38 ;; 39 *) 40 echo "Usage: $0 {start|stop|restart|status}" 41 exit 1 42 ;; 43 esac 44 45 exit $MYRC
Init auf BSD-Art
Die BSD-Variante für den Init-Vorgang ist unter Linux nicht mehr besonders verbreitet. Einige Distributionen wie Arch Linux verwenden immerhin einen hybriden Ansatz, eine Mischung aus System-V- und BSD-Init. Im Unterschied zu System-V kennt das BSD-Init keine Runlevel, auch die Konfigurationsdatei »/etc/inittab« existiert nicht. Die System-Initialisierung erledigt »/etc/rc« , ein langes Shellskript, das eine Konfigurationsdatei unter »/etc/rc.conf« besitzt. Es gibt dabei also keine dienstspezifischen Skripte. Will der Admin einen Dienst einschalten, muss er »rc.conf« anpassen und ihn manuell starten. Das Ändern der Konfigurationsdatei stellt nur sicher, dass der entsprechende Prozess auch nach einem Reboot läuft.
Die Integration eigener Dienste erfolgt in der Datei »/etc/rc.local« beziehungsweise in »/etc/rc.shutdown« . Für Prozesse, die dem System unbekannt sind, fügt der Admin die entsprechenden Codezeilen in diese Shellskripte ein. Da es sich um pures Shellscripting handelt, kann er den entsprechenden Code auch in ein externes Skript auslagern, das auf Wunsch sogar die Argumente »start« und »stop« versteht. Auf diese Weise ist es einfacher, die Prozesse zur Laufzeit zu stoppen oder zu starten – analog zum System-V-Ansatz. Abbildung 2 illustriert die Integration des Beispiel-Dienstes »foobar« in den BSD-Init-Prozess.
Upstart macht Tempo
Das serielle Starten von Diensten beim traditionellen Init-Konzept führt dazu, dass damit ausgerüstete Linux-Distributionen den Großteil des Bootprozesses mit dem Starten der Hintergrunddienste verbringen. Mit Upstart [2] stellte die Ubuntu-Firma Canonical einen neuen Ansatz vor, der in Ubuntu 9.10 erstmals umfangreich zum Einsatz kam. Die starre alphanumerische Ordnung löst Upstart durch ein ereignisgesteuertes Modell ab: Das System passt bestimmte Ereignisse ab, etwa die Aktivierung des Netzwerks oder das Einhängen der Dateisysteme. Diese sind die Voraussetzung, dass bestimmte Dienste starten [3].
Das zentrale Kommando zur Jobverwaltung ist »initctl« : Über »initctl list« erhält der Admin den aktuellen Status aller über Upstart verwalteten Prozesse. Der Befehl »initctl stop foobar« beendet den Dienst »foobar« , das Kommando »initctl start foobar« startet ihn wieder.
Die Jobkonfigurationen finden sich im Verzeichnis »/etc/init/« . Upstart arbeitet dort alle Dateien mit der Endung ».conf« ab (Abbildung 3). Einfaches Umbenennen der Datei, sodass der Name nicht mehr auf ».conf« endet, verhindert den automatischen Start. Übrigens findet der Anwender zwar noch einen Prozess names »init« , aber dahinter verbirgt sich der Upstart-Daemon. Es existiert im Normalfall auch keine »/etc/inittab« mehr – oder nur noch ein Bruchteil davon.

Abbildung 3: Auch der Upstart-Daemon heißt Init, die Konfigurationsdateien befinden sich in »/etc/init/«.
Upstart konfigurieren
Ein Upstart-Job für den Foobar-Dienst ist nicht schwer einzurichten. Im folgenden Beispiel (Listing 4) startet der neue Init-Prozess den Daemon in den Runlevels »2345« und stoppt ihn in den restlichen. Vor dem Start und nach dem Beenden führt Upstart noch jeweils ein Shellkommando aus: Der Admin möchte den Vorgang per »logger« im Syslog mitprotokollieren. Listing 5 zeigt eine interaktive Sitzung, in der der Admin den neu eingerichteten Foobar-Dienst startet, anhält und schließlich deaktiviert.
Listing 4
foobar.conf: Upstart-Job für Foobar-Dienst
01 # foobar - foobar Service 02 # 03 # foobar is a pseudo service 04 05 description "foobar daemon" 06 07 pre-start script 08 logger -p user.err "starting foobar service" 09 end script 10 11 start on runlevel [2345] 12 stop on runlevel [!2345] 13 14 exec /usr/sbin/foobar -d 15 16 post-stop script 17 logger -p user.err "foobar service stopped" 18 end script
Listing 5
Arbeiten mit initctl
01 # initctl status foobar 02 foobar stop/waiting 03 # initctl start foobar 04 foobar start/running, process 2327 05 # initctl status foobar 06 foobar start/running, process 2327 07 # ps -ef|grep [fo]oba 08 root 2327 1 0 13:28 ? 00:00:00 /usr/sbin/foobar -d 09 # 10 # initctl stop foobar 11 foobar stop/waiting 12 # mv /etc/init/foobar.conf /etc/init/foobar.conf.weg 13 # initctl status foobar 14 initctl: Unknown job: foobar
Alles neu: Systemd
Nachdem es lange Zeit so aussah, als würde Upstart das alte Init-System ablösen, betrat 2010 mit Systemd ein neuer Star die Bühne. Benutzer von Fedora 15 finden das neue System bereits als Standard vor. Systemd unterteilt seine Aufgaben in vier Kategorien: Hardware einrichten, Datenträger einbinden, Sockets anlegen und Daemons starten.
Von diesen so genannten Units entspricht die letzte am ehesten den bekannten System-V-Init-Skripten. Setup, Konfiguration und Wartung von Systemd-Units verlangen Umgewöhnung: Das zentrale Tool ist »systemctl« . Damit listet der Admin aktive Units auf, (de-)aktiviert den automatischen Start beim Booten und startet beziehungsweise beendet die entsprechenden Prozesse (Tabelle 4).
Die gute Nachricht vorweg: Systemd versteht auch die klassischen System-V-Init-Skripte. Der Anwender kann also wie gewohnt das Shellskript im Verzeichnis »/etc/init.d/« ablegen und mit Hilfe des Werkzeugs »systemctl« verwalten. Systemd erkennt das Init-Skript im alten Stil und schaltet automatisch auf die Kommandos »chkconfig« oder »insserv« um (siehe Listing 6). Ist ein LSB-Header im Init-Skript vorhanden, wertet auch der Systemd-Daemon ihn aus.
Listing 6
Verwaltung des Foobar-Dienstes mit Systemctl
01 # systemctl --type=service --all|grep foobar 02 foobar.service loaded inactive dead LSB: foobar service 03 # systemctl enable foobar.service 04 foobar.service is not a native service, redirecting to /sbin/chkconfig. 05 Executing /sbin/chkconfig foobar on 06 # systemctl start foobar.service 07 # systemctl status foobar.service 08 foobar.service - LSB: foobar service 09 Loaded: loaded (/etc/rc.d/init.d/foobar) 10 Active: active (running) since Mon, 12 Sep 2011 10:52:44 +0200; 2s ago 11 Process: 967 ExecStart=/etc/rc.d/init.d/foobar start (code=exited, status=0/SUCCESS) 12 Main PID: 969 (foobar) 13 CGroup: name=systemd:/system/foobar.service 14 969 /usr/sbin/foobar -d 15 # 16 # systemctl stop foobar.service 17 # systemctl status foobar.service 18 foobar.service - LSB: foobar service 19 Loaded: loaded (/etc/rc.d/init.d/foobar) 20 Active: inactive (dead) since Mon, 12 Sep 2011 10:53:42 +0200; 1s ago 21 Process: 973 ExecStop=/etc/rc.d/init.d/foobar stop (code=killed, signal=TERM) 22 Process: 967 ExecStart=/etc/rc.d/init.d/foobar start (code=exited, status=0/SUCCESS) 23 Main PID: 969 (code=exited, status=0/SUCCESS) 24 CGroup: name=systemd:/system/foobar.service 25 # systemctl disable foobar.service 26 foobar.service is not a native service, redirecting to /sbin/chkconfig. 27 Executing /sbin/chkconfig foobar off 28 # systemctl status foobar.service 29 foobar.service - LSB: foobar service 30 Loaded: loaded (/etc/rc.d/init.d/foobar) 31 Active: inactive (dead) since Mon, 12 Sep 2011 10:53:42 +0200; 19s ago 32 Main PID: 969 (code=exited, status=0/SUCCESS) 33 CGroup: name=systemd:/system/foobar.service 34 #
Mit ein bisschen Zeit und etwas Lernwillen ist es für den Linux-Benutzer kein Problem, ein Init-Skript in eine Systemd-Unit umzuwandeln. Die Unit-Dateien erinnern an die von Windows bekannten Ini-Dateien und sind im allgemeinen deutlich kürzer als die Init-Skripte. Eine ausführliche Beschreibung der Konfigurationsparameter und weitere Hinweise für Admins gibt es unter [4].
Systemd ist sehr umfassend konfigurier- und bedienbar. Bei einem minimalistischen Ansatz sind aber drei Einträge wichtig: »Unit« , »Service« und »Install« . Jeder Abschnitt enthält eine Anweisung: die Beschreibung des Dienstes, das Kommando zum Starten des Prozesses sowie eine Angabe, in welchem Zustand oder Runlevel Systemd das Startkommando ausführen soll.
Die System-V-Runlevels sind im Target-Konzept von Systemd aufgegangen. Jedes Target beschreibt eine Ansammlung von Units, die Systemd beim Ansteuern des Bootziels startet. Reagiert der Prozess nicht auf das übliche »SIGTERM« -Signal, muss die Unit-Konfiguration auch das Stoppkommando enthalten.
Systemd sucht seine Konfigurationsdateien in den Verzeichnissen »/lib/systemd/system/« und »/etc/systemd/system/« . Letzteres ist für angepasste und selbst entwickelte Dateien vorgesehen. Ist die Unit-Datei platziert, kann der Admin den Dienst über »systemctl start foobar.service« starten. Damit der Dienst auch nach einem Reboot läuft, bindet der Linux-Anwender die Unit-Konfiguration in das unter »Install« definierte Target ein: »systemctl enable foobar.service« . Systemd legt einen Symlink in das entsprechende Target-Verzeichnis – analog zu den Symlinks von System-V-Init.
Meine Einheit
Abbildung 4 zeigt die Unit-Datei für den Beispielprozess Foobar. Der Ansatz erweist sich als etwas weniger spartanisch als oben beschrieben. Im »Unit« -Abschnitt ist festgelegt, dass »crond« auf jeden Fall vorher laufen muss und lokale Anpassungen erst nach dem Foobar-Daemon an der Reihe sind. Beim Festlegen der Start- und Stoppkommandos könnte der Admin auch auf Shellskripte verweisen – sogar ein System-V-Init-Skript funktioniert. In diesem Fall genügt aber der Verweis auf die eigentliche Binärdatei.
Die Ablösung bei den Init-Systemen ist im vollen Gange. Gerade noch setzte Fedora auf Upstart, schon sieht sich der Anwender Systemd gegenüber. Die Konfigurationen des klassischen Init, von Upstart und Systemd unterscheiden sich deutlich. Aber schon nach kurzer Einarbeitung ist es möglich, die notwendigen Skripte, Jobs oder Units anzufertigen und zu verwalten. (mhu)
Infos
- System-V-Init-Skripte laut LSB 4.0: http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
- Upstart: http://upstart.ubuntu.com
- Nico Dietrich, Dirk von Suchodoletz, “Auf die Plätze, fertig …” – Schnelles Booten mit Upstart, einem Ersatz für das betagte Sys-V-Init: Linux-Magazin 02/07, S. 72
- Systemd: http://freedesktop.org/wiki/Software/systemd













