Open Source im professionellen Einsatz
Linux-Magazin 02/2007
© sxc.hu/Dimitris Petridis

© sxc.hu/Dimitris Petridis

Schnelles Booten mit Upstart, einem Ersatz für das betagte Sys-V-Init

Auf die Plätze, fertig ...

,

Lahme Bootzeiten sind lästig. Da hilft auch kein 'Linux läuft über Monate stabil', gefragt sind Schnellstarter, die nach dem Anschalten oder dem per Kernel-Update erzwungenen Reboot nicht erst minutenlang bummeln. Ubuntu entwickelt gerade einen viel versprechenden Ansatz.

1693

Upstart soll den Bootvorgang umkrempeln. Das ambitionierte Projekt [1] aus dem Hause Ubuntu führt dazu einen generischen Init-Daemon ein, der von vielen Entwicklungen moderner Linux-Systeme profitiert. Geschickt vermeidet Upstart unnötige Wartephasen, lässt Startskripte parallel arbeiten und reduziert die Bootzeit auf das Nötige. Längerfristig soll Upstart als generische Schnittstelle für System-Hintergrunddienste auch den At-Daemon, Cron und weitere ablösen. Erste Schritte in Richtung fliegender Start sind im gerade erschienen Ubuntu 6.10 (Edgy Eft) schon erkennbar.

An dem lahmen Bootvorgang haben sich schon viele Projekte versucht [2]. Kein Wunder, denn das minutenlange Booten ihrer ansonsten hochgezüchteten Maschine ärgert die Benutzer. Das gefühlte Missverhältnis ist groß: Obwohl das Herz der Maschine mit 3 Gigahertz pulsiert und die Festplatte rast, bringt die Kiste für Minuten nur einen öden Splashscreen zustande.

Suse Linux 10.1 zum Beispiel braucht auf einem Thinkpad X41 eine Minute, bis sich der Benutzer einloggen darf. Vieles liegt am in die Jahre gekommenen Bootkonzept des Unix-System-V-Inits (siehe Kasten "Sys-V-Init"). Das ehemals revolutionäre Konzept mutierte zum Bremsklotz. Es gibt zwar etliche Tricks, die dem Start etwas auf die Sprünge helfen, als wirkliche Lösungen taugen sie jedoch nicht. Zudem sind viele Turbo-Lader für den normal erfahrenen Linux-Anwender undurchschaubar. Upstart versucht daher eine komplett eigene Herangehensweise, um dem Bootvorgang neuen Schwung zu verleihen.

Sys-V-Init

In frühen Unix-Versionen war ein einfaches Shellskript dafür zuständig, die Maschine zu konfigurieren und Dienste zu starten. Das Konzept beispielsweise von »/etc/rc« aus der BSD-Familie war bestechend simpel, hatte jedoch einen gravierenden Nachteil: Um Drittanbieter-Software oder eigene Erweiterungen einzubinden, waren Änderungen am Shellskript nötig. Dessen Code zu modifizieren ist aber recht gefährlich, bei Fehlern bleibt schnell ein nicht mehr bootfähiges System zurück.

Oft genügt zum Start eines Dienstes kein simples Kommando ohne Parameter, sondern es sind Zusatzinformationen nötig, die je nach Umgebung variieren. So kann beispielsweise der ISC-DHCP-Server auf bestimmten Ethernet-Interfaces statt auf allen Ports lauschen. Damit der Admin für solche Änderungen nicht ebenfalls direkt das Startskript bearbeiten muss, gibt es oft eine Konfigurationsdatei, die das Skript einliest. Das erlaubt Updates der Startskripte, ohne die lokale Konfiguration zu gefährden.

Das Sys-V-Init verwendet gegenüber BSD einen deutlich flexibleren, aber auch komplexeren Ansatz. Es führt mehrere Runlevels ein, die einen bestimmten Zustand der Maschine definieren, abgeleitet von den dann laufenden Prozessen. Es sind acht Runlevels möglich, aber nicht zwingend in allen Systemen auch belegt. Drei Runlevels haben fest definierte Aufgaben: Halt (0), Single User Mode (1) und Reboot (6).

Welche Runlevels festgelegt sind und in welchen Runlevels ein System beim Booten startet, steht in der Datei »/etc/inittab« (siehe Abbildung 1). Das Sys-V-Konzept geht davon aus, dass sich das System standardmäßig in wenigen definierten Zuständen befindet, etwa Betrieb ohne oder mit Netzwerk und mit X11. Einen Wechsel zwischen diesen Runlevels triggert der Sysadmin mit »init Runlevel«.

Ein weiterer Vorteil liegt in den separierten Skripten für jeden Dienst oder Konfigurationsvorgang. So ist es möglich, durch den Aufruf von beispielsweise »/etc/init.d/dhcpd restart« einfach nur den DHCP-Server neu zu starten. Auch die Idee, per Symlink-Sammlung die Auswahl und Reihenfolge der in einem Runlevel nötigen Skripte zu bestimmen, überzeugte.

Abbildung 1: Diese typische »inittab« definiert die Runlevels 0 bis 6 und bestimmt Runlevel 5 als Default. Beim Drücken der Tastenkombination [Ctr]+[Alt]+[Delete] löst Init einen Reboot aus.

Am Anfang steht Init

Auf den meisten Unix-artigen Systemen ruft der Kernel Init auf und gibt ihm die Prozess-ID 1. Der Ablauf ist fest einkompiliert, unter Linux in »/usr/src/linux/init/main.c«. Init startet im Userspace alle weiteren Prozesse und initialisiert die Maschine. Der Prozess und seine Hilfsskripte laden Kernelmodule, prüfen und mounten die Dateisysteme, richten das Netzwerk ein, starten Serverdienste und rufen den grafischen Login-Manager auf. Dabei muss Init die Dienste in einer vernünftigen Reihenfolge anstoßen. Der Abgleich der Systemzeit mit einem Zeitserver im Netz ist erst sinnvoll, wenn die Maschine erreichbar ist. Dazu muss die Netzwerk-Hardware initialisiert und mindestens ein Netzwerk-Interface mit Außenzugang eingerichtet sein.

Die Zahl der Dienste und der im Hintergrund lauernden Agenten hat im Laufe der Jahre zugenommen und den Init-Prozess schwerfällig gemacht. Gerade der Desktop-Einsatz, wie ihn Ubuntu anstrebt, erfordert eine recht dynamische Systemkonfiguration, Mobilgeräte machen dem Sys-V-Init das Leben zusätzlich schwer. Da hängen Dienste von einer funktionierenden Netzwerkverbindung ab, die über wechselnde Devices erst ad hoc aufgebaut wird.

Für diese Zwecke gibt es Tools: »acpid« und »apmd« fürs Powermanagement, HAL-Device-Manager fürs dynamische Einbinden von Laufwerken oder den Resource-Manager für die dynamische Zuweisung der Device-Rechte an den lokal angemeldeten User. Jedes dieser Systeme implementiert seine eigene Konfigurationslogik, die Admins lernen müssen, um eine bestimmte Aufgabe zum richtigen Zeitpunkt erledigen zu lassen.

Nicht alle Prozesse und Dienste sind mit dem Start und Stopp einer Maschine verknüpft. Es gibt spezialisierte Services wie Cron und den At-Daemon, die Prozesse zu bestimmten Zeitpunkten starten. Bisher sind sie in keiner Weise mit dem Runlevel-System verbunden, obwohl ihnen eine ähnliche Logik unterliegt. Auch das will Upstart ändern [4].

Bevor sich die Entwickler von Ubuntu entschieden ein neues System zu entwickeln, haben sie die damals bekannten Sys-V-Alternativen [2] gesichtet. Keines der in Frage kommenden Konzepte erfüllte ihre Erwartungen oder war unter einer akzeptablen Lizenz verfügbar.

Bei ihrem eigenen Entwurf entschieden sich die Entwickler gegen einen ziel- und für einen ereignisorientierten Ansatz. Zielorientiert bedeutet, zu definieren, welche Dienste am Ende des Startvorgangs laufen sollen (KDM, SSH-Daemon ...). Für jeden Dienst sind seine Abhängigkeiten zu definieren, aus denen das Init-System eine sinnvolle Startreihenfolge ableitet. Diesen Weg verfolgen Gentoo mit »depend« (siehe Kasten "Gentoo"), aber auch Suse mit einer abgewandelten Version des Sys-V-Init (siehe Kasten "Suse").

Das Gegenkonzept dazu sind Events. Statt Abhängigkeiten zu formulieren, um die sich ein Skript bei seinem Start womöglich selbst kümmert, läuft ein Skript im Event-System erst dann, wenn alle Vorbedingungen erfüllt sind. Sinnvoll wäre es etwa, einen NFS-Client erst dann aufzurufen, wenn der eingetragene NFS-Server erreichbar ist. Das System, für das sich Ubuntu entschieden hat, versteht auch komplexere Vorbedingungen, etwa "Netzwerkkonfiguration erfolgreich abgeschlossen" und "Apache läuft" oder künftig "USB-Stick angestöpselt".

Gentoo

Gentoo als jüngerer Spross in der Linux-Familie hat das Problem der Runlevelskript-Sortierung auf seine eigene Weise gelöst. Das Runlevelskript selbst ist kein einfaches Bash-Skript mehr, sondern nutzt einen separaten Interpreter: »/sbin/runscript«. Typischerweise hat es folgenden Aufbau:

#!/sbin/runscript
opts="depend start stop restart"
depend() {
  # Abhängigkeiten und Voraussetzungen
}
start() {
  # Kommandos zum Start eines Dienstes
  # inklusive Vorbereitungen
}
stop() {
  # Kommandos zum Anhalten eines Dienstes
  # plus Aufräumaktionen
}
restart() {
  # Restarten eines Dienstes
}

Der String hinter »opts« listet alle vom Runlevelskript zur Verfügung gestellten Funktionen. Wer eigene Funktionen hinzufügen will, nimmt diese in die Liste auf und schreibt einen passenden Funktionsblock mit gleichem Namen. Während die Sektionen »start«, »stop« und »restart« sich nicht vom klassischen Konzept unterscheiden, passiert das Interessante in »depend«. Ein Dienst hängt einerseits von anderen Diensten oder vorbereitenden Einstellungen ab und kann andererseits eine bestimmte Funktionalität liefern, die andere Dienste wiederum brauchen:

  • »need Dienst«: Zwingend angewiesen auf den Dienst
  • »use Dienst«: Verwendet den Dienst
  • »provide Funktionalität«: Stellt eine bestimmte Funktionalität bereit
  • »before Dienst«: Sollte vor dem anderen Dienst starten
  • »after Dienst«: Sollte nach dem angegebenen Dienst starten

Gentoo kennt auch virtuelle Dienste, etwa »net«, der für alle Netzwerktechniken steht (Ethernet, Modem, WLAN). Ähnliches gilt für Mailserver (»mta«). Abhängigkeiten können die Startskripte sogar dynamisch ermitteln, wie das Beispiel »/etc/init.d/syslog-ng« zeigt:

case $(sed 's/#.*//' /etc/syslog-ng/U
syslog-ng.conf) in
  *source*tcp*|*source*udp*|*destinationU
*tcp*|*destination*udp*)
  need net ;;
esac

Wenn keine Abhängigkeiten dagegen sprechen, kann der Admin Dienste auch umsortieren, das passiert über »before« oder »after«.

Suse

Während das traditionelle Sys-V-Init einen streng linearen Ansatz verfolgt, erlauben die Suse-Linux-Versionen seit 10.0 eine Parallelisierung der Bootskript-Aufrufe. Dieses Feature aktiviert der Admin in der Datei »/etc/sysconfig/boot«, indem er die Variable »RUN_PARALLEL« auf »yes« setzt. Damit gilt nicht mehr die traditionell durch »S00skript1« bis »S99skript25« definierte Reihenfolge.

Neue Abhängigkeiten

Stattdessen greifen die in den Dateien ».depend.boot«, ».depend.start« und ».depend.stop« festgelegten Abhängigkeiten. Hat der Administrator einfach ein eigenes Skript, beispielsweise »S12nbd-server«, in »rc3.d« mit einem klassischen Link hinzugefügt, ignoriert das System dies. Das Kommando »insserv« übernimmt die Aufgabe und wertet für die korrekte Auflösung der Abhängigkeiten den Header der Datei aus:

### BEGIN INIT INFO
# Provides: nbd-server
# Required-Start: $network
# Should-Start: $syslog
# Required-Stop:
# Default-Start:  3 5
# Default-Stop:   0 1 2 6
# Description:    Start Network Blockdevice Daemon
### END INIT INFO

Die Komplexität bleibt auf diese Weise vor dem Anwender versteckt, der Ansatz bringt jedoch nicht viel. Bei Tests auf dem im Text erwähnten Thinkpad X41 (mit zugegeben lahmer Festplatte) lagen der Parallelstart mit etwas über einer Minute und der Normalstart mit 70 Sekunden sehr nah aneinander. Dass die Dienste tatsächlich parallel starten, ist aber gut zu erkennen: Die Ausgaben auf dem Bildschirm geraten durcheinander.

Ereignis-Horizont

Events sind im Grunde einfache Zeichenketten. Die möglichen Ausprägungen teilen die Upstart-Autoren in drei Klassen:

  • Einfache Edge-Events, etwa "System startet" oder "Benutzer hat einen Knopf gedrückt".
  • Level-Events erhalten zusätzlich einen Parameter, etwa den Zustand eines Netzwerk-Interface. Dienste und Tasks sollen bei jedem Level-Event laufen oder nur, wenn der Parameter einen bestimmten Wert erreicht hat.
  • Temporale Events, die nach einer bestimmten Zeit oder zu einem definierten Zeitpunkt eintreten.

Die Entwickler hielten sich an den guten Ton der Open-Source-Szene: Release early, release often. So erschien der Code frühzeitig, die Programmierer haben mit Edgy Eft an einem laufenden System selbstbewusst demonstriert, wie weit sie sind. Sie hoffen auf Feedback von Entwicklern anderer Distributionen. Daher kann sich die Upstart-Spezifikation noch ändern. Die hier beschriebenen Beispiele beziehen sich auf die Anfang Dezember aktuelle Version 0.3.

Diese Version schafft es schon, den vorhandenen Init-Prozess zu ersetzen. Noch sind aber bei weitem nicht alle Startskripte auf den Event-Mechanismus umgestellt. Die temporalen Events beherrscht Upstart ebenfalls noch nicht. Geplant ist, als Eventquellen auch andere Programme zu nutzen, etwa Udev und den ACPI- oder APM-Daemon.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 6 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Initsysteme

    Sys-V-Init startete die Prozesse von Linux mehr als ein Jahrzehnt lang als Einzelkämpfer. Doch heute lauert eine technisch versierte Generation von Initsystemen in den Startblöcken.

  • Artikeltipp: Upstart und Systemd im Vergleich

    Upstart und Systemd - gleich zwei neue Ansätze konkurrieren um die Pole-Position beim Linux-Start. Tim Schürmann unterzieht die Kandidaten im LinuxUser 01/2010 einem konzeptionellen Vergleich.

  • Debian holt Upstart ins Boot

    Das derzeitige Debian-Bootsystem Sysvinit soll wegen Unzuverlässigkeit schrittweise durch Upstart ersetzt werden, melden die Bootsystem-Maintainer auf der Entwickler-Announce-Mailingliste.

  • Kraftvolle Schnellstarter

    Wenn es beim Systemstart auf jede Sekunde ankommt, erweist sich der Linux-typische Klassiker Sys-V-Init als lästiger Bremser. Entwickler von Embedded-Geräten und schlanken Spezial-Distributionen sollten Ausschau nach zeitgemäßeren Sprintern halten.

  • Init-Systeme

    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.

comments powered by Disqus

Ausgabe 10/2016

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.