Statt nacheinander wie beim Staffellauf lassen alternative Bootsysteme viele Prozesse parallel anlaufen: ein Massenstart. Dabei benötigen sie manchmal nur die Hälfte der Zeit bis ins Ziel und bieten sich zudem oft noch als Servicemanager an, die ihre Klienten auch nach dem Start betreuen.
Zum Starten braucht ein Rechner Software. Um an Software zu kommen, muss er gestartet sein. Das klassische Henne-Ei-Problem. Jeder Rechner löst es, noch ehe der Benutzer den Finger vom Netzschalter nehmen kann. Und zwar mit Hilfe des Bios. Auf Unix-artigen Systemen gibt es den Startschuss zu einem Staffellauf, dessen Ziel der einsatzbereite Rechner ist. Inzwischen nehmen auf dem Weg dorthin jüngere Konkurrenten dem altgedienten System-V-Init wertvolle Sekunden ab. Zudem sind manche nicht nur schneller, sondern auch vielseitiger. Lohnt ein Wechsel?
Der Ausgangspunkt ist in jedem Fall das Bios. Das Bios kann auch Boot-ROM (Macintosh) heißen oder etwa Open-Boot-Environment (SPARC) – trotz der verschiedenen Namen sind die Funktionen im Prinzip identisch. Die Bootsoftware hat die stromlose Zeit seit dem letzten Shutdown in einem nicht-flüchtigen NVRAM-Speicher überlebt und wird durch die Energiezufuhr beim Einschalten wieder aktiv.
Da sie selbst nur sehr beschränkte Fähigkeiten besitzt, kümmert sie sich sofort um Verstärkung. In einer voreingestellten Reihenfolge sucht sie zunächst die verfügbaren Massenspeicher ab, findet in der Mehrzahl der Fälle eine Festplatte und liest deren erste 512 Byte, den so genannten Master Boot Record (MBR).
Lade-Reihenfolge
Der MBR enthält nämlich einen unverzichtbaren Helfershelfer, ein kleines Programm, das die im selben Speicherbereich abgelegte Partitionstabelle nach einer bootbaren Partition durchforstet. Ist die gefunden, lädt das Bios aus ihrem ersten Sektor den ersten Teil des Bootloaders, der sich danach selbst an den Haaren aus dem Sumpf zieht, indem er seinen eigenen zweiten Teil von der Festplatte nachlädt. Im Hauptspeicher angekommen holt er den großen Bruder des Bios, den Kernel des Betriebssystems, dorthin nach.
Prinzipiell könnte man den Kernel auch direkt durch das Bios laden lassen. Tatsächlich gibt es mit Linuxbios [1] ein solches Projekt. Derzeit unterstützt es aber noch nicht allzu viele Motherboards.
Klassisch
Kaum geladen übernimmt der Kernel Stab und Kommando, denn die Staffel ist noch lange nicht im Ziel: Nun gilt es, das laufende System zu initialisieren und alle erforderlichen Dienste zu aktivieren. Der Kernel delegiert diesen Schritt an den ersten Prozess, den er seinerseits mit der ID 1 ins Rennen schickt, den Urvater aller weiteren Prozesse: »init«. Wie »init« genau vorgeht, hängt ein wenig vom Unix-Derivat ab: Klassische BSD-Systeme sammelten alle Arbeitsanweisungen für »init« in einem einzigen Shellskript, die jüngeren BSD-Abkömmlinge verwenden wie alle System-V-Verwandten einen ganzen Satz aufeinander aufbauender Skripte.
System-V-Init fasst diese Skripte in nummerierten Verzeichnissen zusammen. Hat der Rechner jeweils einen dieser Ordnerinhalte komplett abgearbeitet, gelangt er in einen bestimmten Betriebszustand, auch als Runlevel bezeichnet. In der Regel entspricht Runlevel 1 dem Einzelnutzerbetrieb ohne Netzwerkkonfiguration. In Runlevel 2 kommt das Netzwerk hinzu, in Runlevel 3 der Mehrbenutzerbetrieb, in Runlevel 5 die grafische Oberfläche. Ein Wechsel in Runlevel 0 entspricht einem Shutdown, der Übergang zu Runlevel 6 einem Reboot. Eine Sonderstellung nimmt der Runlevel S ein, in dem nur die allernötigsten Dienste aktiv sind. Dieser Systemzustand wird hin und wieder für Wartungsarbeiten gebraucht.
Welchen Runlevel »init« ansteuern soll, kann ihm der Kernel beim Aufruf als Parameter übergeben. Ansonsten orientiert es sich an einer Tabelle im File »/etc/inittab«. Dort ist nicht nur der Default-Runlevel notiert, sondern beispielsweise auch der Name des Skriptverzeichnisses eines jeden Runlevels.
Verbesserbar
Dies Prozedere hat sich in mehr als drei Jahrzehnten Unix-Geschichte etabliert und vielfach bewährt. Doch traten im Laufe der Zeit auch ein paar prinzipielle Probleme zutage, durch die rasante Hardware-Entwicklung teils noch verschärft. Das betrifft vor allem:
- Die Abhängigkeiten der Runlevel-Skripte untereinander. Das
hergebrachte System kann die Reihenfolge steuern, in der es die
Skripte eines Runlevels abarbeitet. Es kennt aber keinen
Mechanismus, der es daran hindern würde, viel Zeit mit
aussichtslosen Startversuchen zu verplempern, nachdem Dienste am
Anfang einer Abhängigkeitskette keinen Erfolg hatten. Die
darauf aufbauenden Services bemerken die fehlenden Voraussetzungen
nicht und mühen sich daher auf verlorenem Posten, bis ein
Timeout sie erlöst. - Die Geschwindigkeit des Bootvorgangs. System-V-Init arbeitet
streng seriell und absolviert einen Schritt nach dem anderen
(Abbildung 1). Das ist dort, wo ein Dienst auf einem anderen
aufbaut, auch nötig – voneinander unabhängige
Dienste könnten aber gleichzeitig anlaufen, was einen
großen Zeitgewinn brächte. - Die Überwachung einmal gestarteter Dienste. Das
traditionelle Init-System gibt die Verantwortung für einen
Dienst ab, sobald es sein Startskript ausgeführt hat. Die
einzige kleine Ausnahme sind jene Dienste, die
»/etc/inittab« startet, etwa die
»getty«-Prozesse. Für sie ist ein automatischer
Neustart möglich (Respawning). - Die Flexibilität beim Booten, zum Beispiel durch die
Verwendung von Profilen, die an verschiedene Einsatzszenarien
angepasst sind. Die einzige Möglichkeit, die
Systemkonfiguration mit Hilfe von System-V-Init vor dem Booten zu
bestimmen, ist die Wahl eines bestimmten Runlevels. Deren
Granularität ist aber sehr gering.
Abhilfe in allen Punkten verspricht eine ganze Reihe von Lösungen, die im einfachsten Fall nur darauf abzielen, die Skripte zu verbessern, die das klassische »init« ausführt. Schon dieser Ansatz reicht aus, um zumindest bestehende Abhängigkeiten besser zu verwalten.
Etliche Linux-Distributionen gehen diesen Weg. Auf der Habenseite verbuchen sie dabei die Kompatibilität mit dem hergebrachten System. Die meisten Alternativen streben allerdings die Parallelisierung der Startvorgänge an und sind daher zu einem viel radikaleren Schnitt gezwungen. Sie ersetzen den zentralen Systemstarter »init« komplett.
Runit
Runit [2] ist ein Init-Ersatz, der von den Daemontools [3] des bekannten amerikanischen Kryptologen und Methematikers D. J. Bernstein inspiriert ist. Die umstrittenen Lizenzbedingungen verhinderten allerdings ihre Integration in Debian – für Gerrit Pape einer der Gründe, im November 2001 das Konzept in einem eigenen Projekt erneut aufzugreifen.
So entstand Runit, das sein Programmierer dem Linux-Magazin als einen Service-Supervisor erklärt, der sich “nicht nur beim Booten um seine Dienste kümmert, sondern während der ganzen Laufzeit des Systems. Das ist ein eigenes Konzept für die Behandlung der Systemdienste: Sie werden nicht gestartet und dann sich selbst überlassen, sondern durch ein kleines Programm überwacht, das dem Administrator ein Interface für die Verwaltung bietet. Auf diese Weise lassen sich die Daemons starten, neu starten und beenden, Signale versenden oder Statusinformationen abfragen.”

Abbildung 1: Das grafische Protokoll eines herkömmlichen Bootvorgangs auf einem minimalistischen Testsystem, erstellt mit »bootchart«. Gut zu erkennen ist die streng serielle Arbeitsweise beim Starten der Dienste.
Den Bootvorgang gliedert Runit in drei Stadien (Stages): Das erste absolviert alle One-Time-Tasks nacheinander. Das betrifft vor allem die Initialisierung der Hardware sowie das Überprüfen und Mounten der lokalen Filesysteme. In Stage 2 startet Runit weitere Dienste parallel. Jedem Service ist für diesen Zweck in einem Runlevel-Verzeichnis (siehe Abbildung 2) unterhalb von »/etc/runit/runsvdir« ein eigenes Unterverzeichnis zugeordnet. Es muss mindestens ein Skript namens »run« enthalten, das den Dienst startet. Stage 3 schließlich kontrolliert den Shutdown.
Für eventuelle Abhängigkeiten von anderen Diensten ist jedes Startskript selbst verantwortlich: Stellt es fest, dass ihm Voraussetzungen fehlen, beendet es sich wieder mit einem Fehler-Returncode. Der Supervisor-Daemon wird es später, wenn die noch fehlenden Dienste wahrscheinlich laufen, erneut automatisch zu starten versuchen.

Abbildung 2: Das Heimatverzeichnis eines Service unter Runit. Neben den beiden Startskripten »run« und »finish« sammelt ein Unterverzeichnis Meta-Informationen.
Runit kann sich sowohl dem System-V-Init unterordnen und, selbst vom klassischen Init gestartet, nur das Service-Monitoring übernehmen als auch selber System-V-Bootskripte respektive ganze Runlevel nach altem Vorbild starten.
In der Umstellungsphase ist diese Flexibilität ein großer Vorteil. Doch hält der Mischbetrieb auch Stolperstellen parat: So kreiert Runit beispielsweise nicht die Fifo »/dev/initctl«, die »telinit« beim Wechsel des Runlevels zur Kommunikation mit »init« verwendet. Will der Admin ein mit Runit gebootetes System etwa mit »reboot« neu starten, muss er dies via »-f« erzwingen, sonst bricht das Kommando ab, da es den erwarteten Kommunikationskanal nicht findet. Ein Problem, das Runit mit etlichen Konkurrenten teilt.
Alle Bootskripte sind neu zu erstellen. Sie fallen jedoch viel einfacher aus als ihre System-V-Vorbilder, weil sie sich nur noch auf den Start ihrer Prozesse zu konzentrieren brauchen. Die vergleichsweise gute Dokumentation enthält einen großen Fundus an Beispielen.
Runit ist in Paketform für mehrere Linux-Distributionen erhältlich, beispielsweise für Debian, Gentoo, Mandriva, Rocklinux oder LFS. Annvix [4] verwendet es standardmäßig. Zumindest die Diensteüberwachung lässt sich auch unter Mac OS X und Solaris einsetzen.
Cinit
Cinit [5] ist ein alternatives Init-Programm von Nico Schottelius. Es bietet zwar kein Monitoring, hat aber einen anderen Trumpf im Ärmel: Es erlaubt die Definition von Profilen, die festlegen welche Services beim Systemstart zu aktivieren sind. Hier wären etwa Sätze für mehrere Umgebungen oder für mobilen und stationären Betrieb vorstellbar.
Jeder Cinit-Service residiert in einem eigenen Verzeichnis, dass zwei weitere Unterverzeichnisse enthält, die seine Abhängigkeit von anderen Diensten abbilden: Alle, die zwingend aktiv sein müssen, damit der aktuelle Service überhaupt startet, sind in den Ordner »needs« verlinkt. Auf jene Dienste, die zwar verfügbar sein sollten, die notfalls aber auch verzichtbar wären, verweist ein Link unter »wants«.

Abbildung 3: Anstelle von »init« fungiert bei Runit der Prozess »runsvdir« als Vater aller später gestarteten Dienste.
Das Skript für den Start heißt immer »on«, es wird von der optionalen Parameterdatei »on.params« begleitet. In den meisten Fällen handelt es sich bei »on« jedoch gar nicht um ein Skript, sondern nur um einen weiteren Link auf das jeweilige Systemkommando zum Aufrufen des Dienstes.
Das Verfahren, die Service-Abhängigkeiten als Links darzustellen, verursacht allerdings einen nicht unerheblichen Konfigurationsaufwand. Zunächst sind die Beziehungen aller Services untereinander zu erfassen, damit man sie anschließend als Links formulieren kann. Tools, um die bestehenden Dependencies des alten Systems zu übertragen, existieren nicht. Auch lässt sich der durch die Links gebildete Abhängigkeitsbaum nicht visualisieren. Daher können sich leicht Fehler einschleichen oder Abhängigkeiten ganz vergessen werden. Einen solchen Irrtum bringt dann erst der praktische Versuch ans Licht.
Die Fehlersuche unterstützt Cinit nicht durch besondere Hilfsmittel, auch das Logging ist eher rudimentär angelegt. Zudem ist die Dokumentation in Form einer losen Sammlung kleiner Ascii-Files ebenfalls nicht optimal. Immerhin sind auf der Webseite des Projekts zwei Beispielkonfigurationen abrufbar, die modifiziert werden können. Cinit ist im Sourcecode oder als Paket für Debian oder Gentoo verfügbar.
E Initng
“Um meinen Lebensunterhalt zu verdienen, bin ich das Jahr über mit einem Eiscreme-Truck als Verkäufer unterwegs”, erzählt Jimmy Wennlund. “Aber im kalten Schweden, wo ich lebe, läuft das Geschäft im Winter nicht besonders und so blieb häufig ein wenig Zeit, um den Laptop aus der Tasche zu holen. Bis der gebootet hatte, vergingen allerdings immer zwei oder drei Minuten – und danach musste ich schon fast wieder weiter. Ich fand das sehr ärgerlich und so begann an einem kalten Dezembertag im Eiscreme-Truck das, was heute Initng ist.”
Initng [6] ist mittlerweile einer der Klassiker unter den Bootbeschleunigern. Er beherrscht den Parallelstart voneinander unabhängiger Dienste (Abbildung 4), verkürzt so die Zeit bis zum Login und bietet außerdem einen umfangreichen Servicemonitor, der es unter anderem gestattet, nachträglich die Historie des Bootprozesses zu inspizieren.
Er kann auch Dienste automatisch neu starten und kennt einen besonderen Warmstart, der alle Services beendet und erneut aktiviert, ohne dass der Rechner tatsächlich bootet – eine Funktion, die auch Cinit beherrscht. Das Programm ist modular aufgebaut und durch eigene Plugins erweiterbar.
Auch Initng arbeitet mit eigenen Boot-skripten. Shellcode kommt jedoch nicht zum Einsatz, zur Auswahl stehen ein XML-Dialekt und ein proprietäres Ascii-Format mit eigenem Befehlsvorrat. Mithin sind auch hier sämtliche Skripte neu anzulegen. Allerdings wird das Programm mit einem umfangreichen Set vorgefertigter Beispiele geliefert, sodass in vielen Fällen faktisch nur noch Anpassungen nötig sind.
Minit
Minit [9] von Felix von Leitner ist wie Runit ein entfernter Abkömmling der Daemontools [3]. Dagegen erinnern die explizite Beschreibung der Abhängigkeiten durch ein Ascii-File »depends« sowie die Links- und Parameterfiles in Service-Directories eher an Cinit. (Dessen Autor übrigens auch Autor eines Minit-Howto ist, [10].) Daneben ist Minit auf sparsamen Ressourcenverbrauch optimiert und verwendet die Dietlibc.
Eine eigene Lösung hat es auch für das Problem der Daemons parat, die sich in den Hintergrund verlagern, ihren Vordergrundprozess beenden und sich damit der Überwachung entziehen. Es kontrolliert sie mit einem Tool namens »pidfilehack«, dass sich der Prozess-ID bedient. Daneben existiert der Servicemanager »msvc« mit den üblichen Funktionen zum Starten, Beenden, Benachrichtigen und automatischen Neustarten.
Jinit
Jinit [7] setzt andere Akzente. Angeregt von Richard Goochs Bootskripten [8] zählt es eher zur traditionellen Fraktion. Allerdings verwendet es eine eigene Inittab mit erweiterten Möglichkeiten, die auf Verzeichnisse mit eigenen Startskripten verweist. Diese Skripte berücksichtigen über das Kommando »need« untereinander bestehende Abhängigkeiten, und zwar nicht nur beim Booten. So hätte etwa das Herunterfahren eines Netzwerkinterface zur Folge, das Jinit zuvor alle von ihm abgängigen Netzwerkdienste automatisch beendet.

Abbildung 4: Das Bootchart einer komplexeren Konfiguration mit Initng. Gut zu sehen ist, wie gruppenweise Dienste starten, nachdem ihre Abhängigkeiten erfüllt sind.
Jinit kann auch System-V-Skripte benutzen, was den Umstieg erleichtert. Dadurch ist es, wie sein Autor John Fremlin dem Linux-Magazin erklärt, “extrem leicht einzusetzen. So müssen im ersten Schritt nur die Einträge in der Inittab geändert werden. Später kann man die Bootskripte anpassen, sodass sie Abhängigkeiten beachten”. Eine weitere Besonderheit von Jinit ist die extensive Kommunikation über System-V-Message-Queues, die es beim Booten vom Filesystem unabhängig machen.
Wertung
Eine gewisse Experimentierfreude und einen verregneten Feierabend braucht es schon, um dem Rechner Beine zu machen. Lohn der Mühe ist eine maximal um knapp die Hälfte verkürzte Startphase. Der Gewinn ist umso größer, je mehr Dienste parallel starten. Bei dem eher minimalistischen LAMP-System, mit dem die Tester die meisten Boot-Turbos ausprobiert haben, beanspruchten das Laden des Kernels sowie die schlecht verkürzbare Hardware-Initialisierung bereits gut die Hälfte der Startzeit. Entsprechend lagen die Einsparungen nur bei maximal 20 Prozent. Zusätzlich zur Zeitersparnis bekommt man jedoch in vielen Fällen eine verbesserte Verwaltung der Abhängigkeiten und einen Dienstemonitor gratis hinzu.
Gerade dann gibt es aber auch eine zusätzliche Fußangel, denn die Servicewächter reagieren meist auf das vorzeitige Ende des von ihnen gestarteten Prozesses. Eine Strategie, die viele Daemons unabsichtlich torpedieren, indem sie sich selbst beenden, nachdem sie Kindprozesse gezeugt haben.
Das führt unter dem Regime eines solchen Monitors zu wiederholten Neustarts des Daemon in einer Endlosschleife. Abhilfe schaffen die meist vorhandenen Kommandozeilenoptionen, die den Daemon vom Selbstmord abhalten und zum Dienst im Vordergrund verpflichten (»httpd -D NO_DETACH«, »syslogd -n«, »sshd -D« und so weiter).
Auf Kompatibilität mit dem hergebrachten Init-System legt keiner der Konkurrenten gesteigerten Wert, was zur Folge hat, dass Installationsroutinen, die versuchen Init-Skripte anzulegen, ins Leere laufen. An dieser Stelle ist also auch später regelmäßig Handarbeit angesagt. Ein Produkt, das alle möglichen Vorzüge gegenüber dem klassischen Bootsystem vollständig in sich vereinen würde, gibt es unter Linux wohl nicht, aber Projekte wie Runit oder Initng machen einen recht ausgereiften Eindruck und locken mit handfesen Voreilen.
Die Dokumentationen der alternativen Bootsysteme sind in vielen Fällen verbesserbar. Ein Umstand, der umso schwerer wiegt, weil ein Irrtum schnell dazu führt, dass der Rechner sich aufhängt und dann keine Informationen mehr preisgibt. Deshalb empfiehlt es sich unbedingt, das neue Bootkonzept zunächst parallel zum alten zu installieren. Die Tester des Linux-Magazins haben alle Systeme zuerst auf virtuellen VMware-Maschinen laufen lassen.
|
Infos |
|---|
|
[1] Linuxbios: [http://www.linuxbios.org/index.php/Main_Page] [2] Runit: [http://smarden.org/runit/] [3] Daemontools: [http://cr.yp.to/daemontools.html] [4] Linux mit Runit: [http://annvix.org] [5] Cinit: [http://linux.schottelius.org/cinit] [6] Initng: [http://initng.thinktux.net/index.php/Main_Page] [7] Jinit: [http://john.fremlin.de/programs/linux/jinit/] [8] Richard Goochs Bootskripte: [http://www.atnf.csiro.au/people/rgooch/linux/boot-scripts/] [9] Minit: [http://www.fefe.de/minit/] [10] Minit-Howto: [http://nico.schotteli.us/papers/linux/howto/minit-howto/index.html] |






