Sobald der Linux-Kernel die Hardware in Beschlag genommen und alle Treiber geladen hat, übergibt er die Kontrolle an das kleine Programm »init
«
. Ihm kommt die Aufgabe zu, den Rest des Systems einzurichten und hochzufahren. Bis vor wenigen Jahren nutzten noch fast alle Linux-Distributionen das so genannte System-V-Init mit seinem geliebten wie gehassten Runlevel-Konzept. Es startete brav einen Dienst nach dem anderen, was zu teilweise recht langen Bootzeiten führte.
Bei Canonical begann man deshalb 2006 mit der Entwicklung eines flotteren Ersatzes. Das Ergebnis namens Upstart fährt seitdem vor allem bei Ubuntu-Distributionen sowie Red Hat Enterprise Linux (RHEL) 6 die Dienste hoch.
Gegenüber dem alten System-V-Init versucht Upstart alle notwendigen Dienste und Programme möglichst parallel zu starten. Darüber hinaus kann es auf bestimmte Ereignisse reagieren, beispielsweise wenn man während des Betriebs eine Festplatte einstöpselt oder austauscht. Schließlich beobachtet es auf Wunsch ohne umständliche Krücken die gestarteten Prozesse und startet sie bei einem Absturz automatisch neu. Um das alles leisten zu können, bricht es vollständig mit dem alten Runlevel-Konzept. Wer damit noch arbeiten muss, sollte im Folgenden kurz sein altes Wissen vergessen.
Um ein Linux-System vollständig hochzufahren, muss Upstart verschiedene Aufgaben durchführen – wie etwa das Netzwerk aktivieren oder den Webserver »httpd
«
starten. Jede dieser Aufgaben bezeichnet Upstart als Job, den es allerdings immer nur dann bearbeitet, wenn zuvor ein passendes Ereignis eingetreten ist. Ein solches Ereignis könnte beispielsweise "Netzwerk aktiviert" oder "Druckerdaemon gestartet" sein. Gibt es zu einem Ereignis mehrere Jobs, so versucht Upstart, sie parallel zu bearbeiten. Das alles erfolgt vollautomatisch: Ein Webserver muss Upstart nur mitteilen, dass er gerne beim Ereignis "Netzwerk aktiviert" starten möchte. Um alles andere kümmert sich Upstart.
Jeder Job besitzt im Unterverzeichnis »/etc/init
«
eine eigene Konfigurationsdatei mit der Endung ».conf
«
. So finden sich beispielsweise in »cups.conf
«
alle Informationen, die Upstart zum Aktivieren des Cupps-Druckerdaemon kennen muss. Der Dateiname ohne Endung ist gleichzeitig der offizielle Name des Jobs.
Bester Freund des Administrators ist das zu Upstart gehörende Werkzeug »initctl
«
. Es kontrolliert und verwaltet sämtliche Jobs. Beispielsweise listet der Befehl
initctl list
sämtliche Jobs und ihren aktuellen Status auf (Abbildung 1). In jeder Zeile steht ganz vorne der Name eines Jobs. Der Begriff vor dem Schrägstrich verrät, ob der Job zuletzt gestartet (»start
«
) oder angehalten (»stop
«
) wurde. Nach dem Schrägstrich folgt sein aktueller Zustand. Sofern ein Job beziehungsweise der durch ihn gestartete Dienst läuft, steht am Ende auch gleich noch seine Prozess-ID. Einen laufenden Job beendet
initctl stop jobname
Damit man sich nicht immer die Finger wund tippen muss, darf man alternativ auch einfach nur
stop jobname
aufrufen. »stop
«
ist schlicht ein Wrapper-Skript für »initctl stop
«
, das ebenfalls zum Upstart-Paket gehört und normalerweise in »/sbin
«
liegt. In jedem Fall sendet Upstart dem betroffenen Prozess zunächst ein SIGTERM-Signal und wartet dann standardmäßig fünf Sekunden. Wenn der Dienst danach immer noch laufen sollte, beendet Upstart ihn umgehend mit dem SIGKILL-Signal. Ein einmal ausgesprochenes »initctl stop
«
ist somit endgültig.
Neben »stop
«
gibt es natürlich auch noch »start
«
und »restart
«
, die einen Job starten beziehungsweise neustarten. Tabelle 1 fasst die wichtigsten »initctl
«
-Befehle zusammen (zu den noch unbekannten Befehlen gleich noch mehr). Apropos »/sbin
«
: Darin liegt auch Upstart selbst unter dem Namen »init
«
, damit Linux es auch garantiert findet.
Wer einen eigenen Dienst beim Booten hochfahren lassen möchte, braucht eine neue Job-Datei. Im einfachsten Fall besteht diese aus lediglich einer einzigen Zeile:
exec /usr/bin/messd --log=/var/log/laerm/messung.log
Hinter »exec
«
steht schlicht das Programm beziehungsweise der Dienst, den Upstart ausführen soll. Hier im Beispiel nimmt ein Lärmmessprogramm seine Arbeit auf, das unablässig über entsprechende Hardware den Schallpegel misst und seine gesammelten Messergebnisse in der angegebenen Logdatei ablegt. Sobald man die obige Zeile in einer Datei wie beispielsweise »messen.conf
«
verstaut und diese bei ihren Kolleginnen unter »/etc/init
«
geparkt hat, kann man die Messsoftware bereits als Administrator per
sudo start messen
hochfahren beziehungsweise via
sudo stop messen
beenden. In der Regel möchte man den Dienst automatisch beim Booten starten. In diesem Fall muss man die Job-Datei wie in Listing 1 noch etwas erweitern.
Listing 1
Beispiel für eine einfache Job-Datei
Kommentare beginnen wie von Shellskripten gewohnt mit einem Hash (#). Hinter »start on
«
steht der Name eines Ereignisses. Sobald es eintritt, aktiviert Upstart automatisch den Dienst. Anstelle von »exec
«
darf man übrigens auch ein Skript einbinden:
script # kleines Bash-Skript: if [...]; then ... fi end script
Upstart führt dann nicht ein Programm aus, sondern arbeitet die Shellbefehle zwischen »script
«
und »end script
«
ab. Die Job-Dateien selbst sind übrigens reine Textdateien und sollten möglichst nicht ausführbar sein.
Die Upstart-Ereignisse, auf die ein Job warten kann, können aus mehreren Quellen stammen. Sobald Upstart die Arbeit aufnimmt, erzeugt es automatisch selbst ein Ereignis mit dem Namen »startup
«
. Ein Dienst, der mit der Anweisung
start on startup
nur auf dieses Ereignis wartet, kann daher weder mit einem funktionierenden Netzwerk noch mit einem vorhandenen Dateisystem rechnen. Im Weiteren entsteht immer dann ein Ereignis, wenn irgendein Job startet oder stoppt. Mit der Zeile
start on starting rsyslog
würde Upstart etwa das Lärmmessprogramm gleichzeitig mit »rsyslog
«
starten. Möchte man sicherstellen, dass »rsyslog
«
schon läuft, nutzt man »started
«
:
start on started rsyslog
Damit würde das Lärmmessprogramm erst nach »rsyslog
«
loslegen – wann genau, lässt sich nicht vorhersagen. Man muss folglich damit rechnen, dass möglicherweise »rsyslog
«
noch nicht vollständig funktioniert. Schließlich kann Upstart den Job auch anwerfen, sobald sich ein anderer Dienst beendet beziehungsweise nicht läuft:
start on stopped rsyslog
Eine weitere Ereignisschleuder sind Systemdienste, allen voran der Gerätemanager »udev
«
. Beim Einstöpseln eines neuen Gerätes erzeugt er ein Ereignis der Form »sub-device-action
«
. »sub
«
steht dabei für das entsprechende Udev-Subsystem und »action
«
für die ausgeführte Aktion. Ein neu angeschlossener Datenträger löst beispielsweise das Ereignis »block-device-added
«
aus.
Eine unvollständige Liste mit den grundlegenden und zumindest in jedem Ubuntu-System vorhandenen Ereignissen liefert die Manpage »man upstart-events
«
(Abbildung 3). Eine weitere Quelle sind die schon vorhandenen Job-Dateien unter »/etc/init
«
.
Abschließend kann ein Administrator mit »initctl
«
ein eigenes Ereignis auslösen:
initctl emit meinereignis
Diesen Befehl darf natürlich auch ein Skript in der Job-Datei aufrufen. Damit es nicht Upstarts Planungen durcheinanderwürfelt, muss man die Job-Datei dann noch mit der Zeile
emit meinereignis
würzen. Sie kündigt formal an, dass der Job irgendwann das Ereignis »meinereignis
«
auslöst. Sofern ein Job mehrere Ereignisse absetzen möchte, führt man sie jeweils in einer eigenen Zeile auf, wie etwa:
emit start-messung emit ende-messung
Die »emit
«
-Angaben benötigt übrigens auch zwingend »initctl check-config
«
, um die Abhängigkeiten zwischen den Jobs korrekt überprüfen zu können (siehe Kasten "Troubleshooting").