Schneller booten mit Upstart

Ein Großteil der Bootzeit heutiger Linux-Systeme geht für die Systeminitialisierung und den nicht-parallelisierten Start Dutzender Daemons drauf. In Ubuntu 9.10 haben die Entwickler begonnen, den starren Startvorgang durch den massiven Einsatz von Upstart zu parallelisieren und zu beschleunigen.

In Pocket speichern vorlesen Druckansicht 30 Kommentare lesen
Lesezeit: 17 Min.
Inhaltsverzeichnis

Aktualisierte Version des Artikels "Blitzstarter, Upstart als Alternative zu SysV-Init unter Linux" aus c't 9/09, S. 176

Die Ladezeit des Linux-Kernels macht nur noch einen kleinen Teil der Zeit aus, die man bei jedem Systemstart auf den Login-Prompt wartet. Die meiste Zeit wartet der Rechner darauf, dass das von Unix System V abstammende init durch die verschiedenen Runlevel wechselt und dabei unzählige Init-Skripte nacheinander abarbeitet. Bei Ubuntu und Fedora hat Upstart schon länger das traditionelle SysV-Init abgelöst.

Daran, dass die Dienste nacheinander in fester Reihenfolge starten, hat sich bislang jedoch nichts geändert – es hatte einfach noch niemand damit begonnen, die Init-Skripte der Dienste an die Möglichkeiten von Upstart anzupassen. Stattdessen emulierte man nur die Runlevel von SysV-Init (die es auf Systemen mit Upstart eigentlich gar nicht mehr gibt) und rief weiterhin die alten Init-Skripte auf. Bei Ubuntu 9.10 haben die Entwickler endlich einen Teil der Dienste auf Upstart umgestellt.

Sowohl Upstart als auch SysV-Init werden vom Kernel als erster Prozess mit der ID 1 gestartet, sobald dieser gebootet und etwaige Boot-Skripte aus der Initial Ramdisk (Initrd) abgearbeitet hat. Bei SysV-Init ist die Datei /etc/inittab der Dreh- und Angelpunkt für die Systeminitialisierung. Hier findet SysV-Init den Default-Runlevel, den Namen des ersten Initialisierungs-Skripts sowie die Kommandos zur Initialisierung der jeweiligen Runlevel. Bei der Initialisierung der Runlevel werden dann die im jeweiligen Runlevel-Verzeichnis (etwa /etc/rc5.d) verlinkten Init-Skripte nacheinander gestartet.

Dabei müssen sich alle Dienste als Daemon in den Hintergrund legen und von der Konsole abkoppeln, weil ansonsten das Init-Skript blockiert würde, bis der Dienst beendet ist. Durch die Abkoppelung kann Init nur mit erheblichem Aufwand feststellen, ob ein Dienst läuft oder sich beendet hat – meist, indem der Daemon eine Datei mit seiner Prozess-ID (PID) in /var/run hinterlegt, wobei es dem Init-Skript obliegt, festzustellen, ob die genannte PID überhaupt zum gewünschten Daemon gehört. Eines der letzten Init-Skripte startet die grafische Oberfläche. Hat SysV-Init alle Skripte ausgeführt, werden schließlich die in der Datei /etc/inittab aufgeführten Dienste wie Login-Konsolen gestartet und überwacht.

Upstart hingegen arbeitet Event-orientiert mit sogenannten Jobs, wobei jede Job-Datei im Verzeichnis /etc/init für den Start eines Dienstes oder einen bestimmten Teil der Systeminitialisierung zuständig ist. Eine feste Reihenfolge gibt es nicht, stattdessen gibt jeder Job an, auf welche Events er reagieren möchte. Tritt ein Event auf, startet Upstart parallel alle Jobs, die auf dieses Event gewartet haben.

Das erste Event, startup, erzeugt Upstart beim Aufruf automatisch selbst. Zudem erzeugen Start und Ende eines jeden Jobs weitere Events, nämlich started Jobname und stopped Jobname. Für das Event startup interessieren sich unter Ubuntu 9.10 diverse Jobs, darunter hostname zur Einrichtung des Rechnernamens; die zugehörige Job-Datei ist /etc/init/hostname.conf. Das nachfolgende Beispiel zeigt eine stark vereinfachte Variante des Jobs:

start on startup
task
exec hostname -b -F /etc/hostname

Das Schlüsselwort start on benennt das Event, bei dem dieser Job laufen soll. Gibt es mehrere Events, auf die der Job reagieren soll, so müssen diese Events logisch miteinander verknüpft werden:

start on (runlevel [016]
and (stopped gdm
or stopped kdm
or stopped xdm))

Anders als noch in Ubunut 9.04 darf start on nicht mehrfach vorkommen. Muss der Job zu einem späteren Zeitpunkt wieder beendet werden, definiert man per stop on zusätzliche Stop-Events, bei denen der Job wiederum abgearbeitet wird.

Will man einen Job außer der Reihe starten oder anhalten, so kann man dies per

initctl start Jobname

respektive

initctl stop Jobname

tun. Welches Programm der Job aufruft, steht hinter exec. Ein großer Unterschied zwischen Upstart und SysV-Init ist, dass in den Init-Skripten Dienste immer im Hintergrund starten, weil sie sonst Init blockieren. Upstart hingegen erwartet, dass der hinter exec genannte Prozess im Vordergrund läuft – denn nur so lange dieser Prozess läuft, betrachtet Upstart den Job als laufend (running). Endet ein mit exec gestarteter Prozess, so endet für Upstart auch der Job und wartet darauf, dass wieder ein passendes Event auftritt (waiting). Dabei merkt sich Upstart den Zustand jedes Jobs, der in /etc/init gelistet ist. Diese Informationen können Sie mit den Befehlen initctl list und initctl status Jobname abrufen.