Die meisten Distributionen bürden den kompletten Systemstart einem kleinen Programm namens Init auf, das den Job wiederum ganz ungeniert an eine wilde Bande aus Skripten delegiert. Mit denen gilt es zu kämpfen, gerät der Bootprozess einmal ins Stocken.
Direkt nachdem der Linux-Kernel die Hardware unter seine Kontrolle gebracht hat, startet er das Programm /sbin/init – und lehnt sich anschließend erst einmal zurück. Init bleibt jetzt die Aufgabe, alle notwendigen Dienste und Anwendungen zu starten, die für ein voll funktionsfähiges Linux-System notwendig sind. Als erster Prozess im System erhält Init die PID 1. Es bleibt zudem die gesamte Betriebszeit über im Hauptspeicher und lässt sich auch durch Abschussversuche à la kill -9 1 nicht beenden (Abbildung 1). Auf diese Weise kann Init unter anderem lebenswichtigen Prozesse neu starten, falls sich diese einmal unerwartet verabschieden.
Hohes Niveau
Hin und wieder möchte man beim Systemstart nur einen ganz bestimmten Teil der Dienste anwerfen. Bereitet beispielsweise die grafische Oberfläche Probleme, wäre es gut, wenn Init sie unbeachtet auf der Festplatte liegen lassen und nur eine einfache Textkonsole hervorholen würde. Um das zu ermöglichen, setzen die meisten Linux-Distributionen ein Init-Programm ein, das mit dem etwas gewöhnungsbedürftigen Konzept der Runlevel arbeitet. Das hoben in den 80er Jahren die Entwickler des Betriebssystems UNIX System V aus der Taufe, weshalb man ein danach arbeitendes Init auch als System-V-Init oder kurz SysV-Init bezeichnet.
Dahinter steht die Idee, dass Init den Computer in einem ganz bestimmten Zustand hinterlässt. So sitzt man nach dem Booten einer Distribution meist vor einem KDE- oder Gnome-Desktop mit funktionierender Netzwerkanbindung. Ein anderer möglicher Systemzustand wäre eine reine Textkonsole ohne Netzwerk oder gar der ausgeschaltete Computer. Ein SysV-Init unterscheidet acht solcher Systemzustände, die man als Runlevel bezeichnet. Zu jedem Runlevel gehört ein Bündel aus Diensten und Programmen, die am Ende des Bootvorgangs aktiv sein sollen. Init teilt man die Nummer des gewünschten Runlevels mit, woraufhin das Programm dann zusammen mit zahlreichen Hilfsskripten den gewünschten Systemzustand herstellt.
TIPP
Stellen Sie sich einen Runlevel einfach als eine von acht möglichen Systemkonfigurationen vor.

who -r nennt den aktuellen Runlevel.” width=”300″ height=”110″ />
Abbildung 2:who -r nennt den aktuellen Runlevel. Das funktioniert sogar im laufenden System: Wenn Sie als Benutzer root das Kommando /sbin/init 0 eintippen, wechselt Init umgehend in den Runlevel mit der Nummer 0. Dazu beendet es zunächst den aktuellen Runlevel, indem es alle nicht benötigten Dienste stoppt. Anschließend aktiviert es den neuen Runlevel 0. Da dieser dem Systemzustand “Computer ausgeschaltet” entspricht, fährt Init dabei Linux herunter. Analog dient der Runlevel 6 dem Neustart (Reboot) des Systems. Der Runlevel mit der Nummer 1 führt zu einem Einzelbenutzer-Betrieb, der (genau wie der spezielle Runlevel S) vorwiegend für Wartungsarbeiten gedacht ist. In der Regel darf sich dort nur der Benutzer root anmelden.
Alle übrigen Runlevel belegt jede Distribution etwas anders. Die Macher von OpenSuse 11.3 beispielsweise haben sich für die Konfiguration aus der Tabelle “OpenSuse 11.3: Runlevel” entschieden. Was dort der Runlevel 5 ist, entspricht unter Debian wiederum dem Runlevel 2.
OpenSuse 11.3: Runlevel
| Nummer | Beschreibung |
|---|---|
| 0 | Computer ausschalten (“Shutdown”) |
| S | Einzelbenutzermodus ohne Netzwerk (englisch “Single User Mode”) |
| 1 | Einzelbenutzermodus ohne Netzwerk |
| 2 | Mehrbenutzermodus ohne Netzwerk |
| 3 | Mehrbenutzermodus mit Netzwerk, aber ohne grafische Oberfläche |
| 4 | ungenutzt |
| 5 | Mehrbenutzerbetrieb mit Netzwerk und grafischer Oberfläche (Standard) |
| 6 | Neustart des Systems (“Reboot”) |
TIPP
Wenn Sie Ihr Linux-System in einem ganz bestimmten Runlevel starten möchten, hängen Sie einfach seine Nummer an den Bootprompt an.
Aktionsplan
Welche Runlevel zur Verfügung stehen, was diese bewirken und welchen davon Init standardmäßig nach dem Einschalten des Computers startet, das regelt die Konfigurationsdatei /etc/inittab. Ein Beispiel für ihren Aufbau zeigt Listing 1: Es zeigt die inittab von OpenSuse 11.3, aus Gründen der Übersichtlichkeit in einer leicht gekürzten Fassung.
Listing 1
# The default runlevel is defined here id:5:initdefault: # First script to be executed si::bootwait:/etc/init.d/boot l0:0:wait:/etc/init.d/rc 0 l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 #l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 ls:S:wait:/etc/init.d/rc S ~~:S:respawn:/sbin/sulogin # what to do when CTRL-ALT-DEL is pressed ca::ctrlaltdel:/sbin/shutdown -r -t 4 now # what to do when power fails/returns pf::powerwait:/etc/init.d/powerfail start pn::powerfailnow:/etc/init.d/powerfail now #pn::powerfail:/etc/init.d/powerfail now po::powerokwait:/etc/init.d/powerfail stop # getty-programs for the normal runlevels 1:2345:respawn:/sbin/mingetty --noclear tty1 2:2345:respawn:/sbin/mingetty tty2 3:2345:respawn:/sbin/mingetty tty3 4:2345:respawn:/sbin/mingetty tty4 5:2345:respawn:/sbin/mingetty tty5 6:2345:respawn:/sbin/mingetty tty6
Jede der Zeilen folgt einem identischen Strickmuster und besteht aus vier Spalten, die jeweils ein Doppelpunkt voneinander trennt:
l5:5:wait:/etc/init.d/rc 5
Die erste Spalte gibt der Zeile einen eindeutigen Namen, der aus maximal vier Zeichen bestehen darf – im obigen Beispiel das Kürzel l5. Was genau Init im Runlevel aus der zweiten Spalte machen soll, bestimmen die in der dritten Spalte angegebene Aktion (sie auch Tabelle “Aktionen”) und das in der vierten Spalte vermerkte Kommando. Im Beispiel würde Init im Runlevel 5 den Kommandozeilenbefehl /etc/init.d/rc 5 absetzen und dann warten (wait), bis dieser komplett abgearbeitet wurde.
Die Aktion initdefault bestimmt den Standard-Runlevel nach dem Booten. Gemäß Zeile 2 von Listing 1 handelt es sich dabei unter OpenSuse 11.3 um den Runlevel 5. Ein Befehl ist hier überflüssig, die letzte Spalte bleibt daher leer. Noch bevor Init in diesen Runlevel wechselt, führt es das Skript /etc/init.d/boot aus, wie es die Aktion bootwait in Zeile 5 fordert:
si::bootwait:/etc/init.d/boot
Da die Aktion auf die Angabe eines Runlevels verzichten kann, bleibt die zweite Spalte hier leer. Das Skript /etc/init.d/boot initialisiert unter OpenSuse unter anderem den Fortschrittsbalken des Bootbildschirms und hängt das /proc-Dateisystem ein. Andere Distributionen nutzen dazu ein anderes Skript; unter Debian sieht die korrespondierende Zeile etwa wie folgt aus:
si::sysinit:/etc/init.d/rcS
Die Aktion sysinit funktioniert wie bootwait, Init führt sie aber noch vor bootwait aus (was Debian aber gar nicht mehr ausnutzt).
Aktionen
boot |
Init führt das Kommando während des Hochfahren aus, ohne die Runlevel-Spalte zu beachten. |
bootwait |
Wie boot, jedoch wartet Init auf das Ende des Kommando-Prozesses. |
ctrlaltdel |
Sagt Init, welcher Befehl auf die Tastenkombination [Strg]+[Alt]+[Entf] antworten soll. |
initdefault |
Der Runlevel, in dem das System nach dem Hochfahren startet. Die Kommando-Spalte bleibt unbeachtet. |
once |
Der Befehl wird nur einmal beim Wechsel des Runlevels gestartet. |
powerfail |
Init führt das Kommando beim Ausbleiben der Stromzufuhr aus. |
powerokwait |
Init führt das Kommando beim Ausbleiben der Stromzufuhr aus und wartet auf das Ende des Prozesses. |
powerwait |
Wie powerfail, jedoch wartet Init auf das Ende des Prozesses. |
sysinit |
Init führt das Kommando während des Bootens vor den Anweisungen aus boot und bootwait aus. |
respawn |
Init startet das Kommando erneut, falls der entsprechende Prozess terminiert. |
wait |
Init wartet auf die Abarbeitung des Kommandos. |
Wiederbelebung
Im unteren Bereich der inittab aus Listing 1 geht es noch einmal etwas kryptisch zu. Dort legt zunächst die Zeile 18 mit
ca::ctrlaltdel:/sbin/shutdown -r -t 4 now
fest, dass Init bei einem Druck auf die Tastenkombination [Strg]+[Alt]+[Entf] das Skript shutdown aufruft und den Computer somit neu startet (Parameter -r). Das soll in jedem Runlevel funktionieren, weshalb in der zweiten Spalte eine spezifische Angabe fehlt. Die Tastenkombination funktioniert übrigens nur in einer reinen Textkonsole, die grafische Oberfläche in Form des X-Servers fängt sie standardmäßig ab. Alle folgenden Aktionen ab Zeile 21 mit power... im Namen weisen Init an, bei einem Stromausfall schnell eine externe Stromversorgung (UPS) ein- beziehungsweise später wieder auszuschalten.
Die Aktion respawn führt wie wait die Anwendung in der vierten Spalte aus. Sollte sich der zugehörige Prozess allerdings irgendwann beenden, startet ihn Init automatisch neu. Die Zeilen 27 bis 32 in Listing 1 sorgen beispielsweise so dafür, dass in den Runleveln 2 bis 5 grundsätzlich sechs Textkonsolen zur Verfügung stehen (die Sie über [Alt]+[1] bis [Alt]+[6] erreichen.
Bei den Ziffern in der ersten Spalte handelt es sich ausnahmsweise nicht um Namenskürzel, sondern um die Nummer des Geräts (die Zahl hinter tty). Wie die sechs Zeilen zudem zeigen, darf die zweite Spalte durchaus mehrere Runlevel hintereinander aufführen. Der Parameter --noclear schließlich sorgt dafür, dass diese erste Konsole nicht alle Meldungen des Bootprozesses sofort löscht.
Subunternehmer
Sobald Init durch den Kernel geweckt wurde, liest es also die Datei /etc/inittab ein, führt dann unter OpenSuse 11.3 gemäß Zeile 5 in Listing 1 zunächst das Skript /etc/init.d/boot aus und wechselt schließlich in den Runlevel 5, indem es das Skript /etc/init.d/rc startet. Dieses wiederum aktiviert die eigentlichen Dienste – welche, das hängt vom Runlevel ab. Dessen Nummer übergibt Init deshalb als Parameter an das Skript, wie ein schneller Blick auf Listing 1 verrät. Unter OpenSuse 11.3 ist es standardmäßig die 5).
l0:5:wait:/etc/init.d/rc 5
Doch auch rc macht sich seine Arbeit leicht: Zunächst wechselt es abhängig vom Runlevel in eines der Unterverzeichnisse rc0.d bis rc6.d. Im Beispiel unter OpenSuse würde es das Verzeichnis rc5.d betreten. Dort ruft es einfach alle vorhandenen Skripte auf, die mit dem Buchstaben S (für “Start”) beginnen. Die Startreihenfolge bestimmt dabei die Nummer, die nach dem S folgt: S07alsasound startet beispielsweise das Audiosystem Alsa, S09cups zwei Skripte später das Drucksystem Cups. Analog zu diesen so genannten Startskripten liegen hier noch passende Stoppskripte, deren Namen mit K (für “Kill”) beginnen. Sie beenden die Dienste bei einem Wechsel des Runlevel.
Zeigefinger
Dank dieser Arbeitsteilung muss man einfach nur ein Startskript für einen Dienst schreiben und es im Verzeichnis rc5.d platzieren, um den Dienst beim nächsten Systemstart automatisch anzuwerfen (siehe auch Kasten “Eigenes Startskript”). Dieser Komfort hat aber auch einen Nachteil: Möchte man den Dienst in verschiedenen Runleveln anbieten, gilt es das Skript in alle entsprechende Unterverzeichnisse zu kopieren, hinzu kommen noch die Stoppskripte. Es kommt noch dicker: Bei Änderungen muss man alle Kopien anpassen.
Diese umständliche und fehleranfällige Prozedur vermeiden die Distributionen, indem Sie für jeden Dienst nur ein einziges Skript im Verzeichnis /etc/init.d ablegen. Für das Drucksystem zeichnet beispielsweise cups verantwortlich. Auf diese zentralen Skripte zeigen dann wiederum in den Unterverzeichnissen rc0.d bis rc6.d entsprechende symbolische Verweise.
Unter dem Strich startet also der Linux-Kernel das Programm Init, das wiederum das Skript /etc/init.d/rc 5 aufruft, welches gemäß seines Parameters in das Verzeichnis rc5.d wechselt und dort allen mit S beginnenden symbolischen Verweisen folgt. Dabei stößt es auch auf den symbolischen Verweis namens S09cups, über den es wiederum zum Skript /etc/init.d/cups gelangt, das nun endlich den CUPS-Daemon startet.
Das funktioniert zwar recht gut, ist aber zumindest für Einsteiger etwas verwirrend. Zu allem Überfluss weichen die Verzeichnisnamen von Distribution zu Distribution auch noch ab: So liegen alle symbolischen Links für den Runlevel 5 unter Debian im Verzeichnis /etc/rc5.d, bei OpenSuse 11.3 dagegen in /etc/init.d/rc5.d.
Erste Hilfe
Um einen störenden Dienst vom Systemstart auszuschließen, müssen Sie lediglich seinen symbolischen Verweis aus dem passenden Unterverzeichnis löschen. Um solche Wartungsarbeiten etwas komfortabler zu gestalten, spendieren die meisten Distributionen entsprechende Hilfsprogramme. Besonders häufig trifft man auf das Werkzeug chkconfig, das unter anderem OpenSuse 11.3 beiliegt.
Der als Benutzer root abgesetzte Befehl chkconfig --list zeigt wie in Abbildung 3 an, in welchen Runleveln welche Dienste aktiv sind (on) und in welchen nicht (off).

chkconfig –list liefert die Dienste aller Runlevel.” width=”300″ height=”220″ />
Abbildung 3:chkconfig --list liefert die Dienste aller Runlevel.Um das ALSA-Soundsystem zunächst aus allen Runleveln zu verbannen und es anschließend nur in den Runleveln 3 und 5 wieder zu aktivieren, geben Sie als root die folgenden beiden Befehle ein:
# chkconfig --del alsasound # chkconfig -f alsasound 35
Unter Debian entfernen Sie mit den zwei folgenden Befehlen zunächst den Druckdienst Cups aus allen Runleveln und reaktivieren ihn anschließend nur für die Standard-Runlevel 2 bis 5:
# update-rc.d cups remove # update-rc.d cups default
Für noch mehr Komfort sorgen grafische Werkzeuge, wie etwa unter OpenSuse 11.3 das YaST-Modul Systemdienste (Runlevel) aus der Rubrik System (Abbildung 4). Dort legen Sie im Expertenmodus für jeden Dienst per Mausklick fest, in welchem Runlevel er starten soll. Dazu markieren Sie ihn in der Liste und haken dann am unteren Rand den entsprechenden Runlevel an.

Systemdienste (Runlevel) erlaubt unter OpenSuse einen bequemen Eingriff in die Runlevel.” width=”300″ height=”268″ />
Abbildung 4: Das YaST-ModulSystemdienste (Runlevel) erlaubt unter OpenSuse einen bequemen Eingriff in die Runlevel. Die Startskripte unter /etc/init.d dürfen Sie als Root auch direkt aufrufen und somit gezielt einzelne Dienste ausschalten oder aktivieren. Beispielsweise stoppt sudo /etc/init.d/cups stop das Drucksystem, sudo /etc/init.d/cups start aktiviert es wieder. Viele der Skripte verstehen zudem noch die Parameter restart und status. Der erste startet den zugehörigen Dienst neu, während status Informationen über ihn ausspuckt (Abbildung 5).

status verrät meist nur, ob der Dienst gerade läuft.” width=”300″ height=”83″ />
Abbildung 5: Der Parameterstatus verrät meist nur, ob der Dienst gerade läuft.Eigenes Startskript
Möchten Sie einen eigenen Dienst automatisch beim Booten mitstarten lassen, gilt es dazu ein passendes Skript zu schreiben. Dieses muss zumindest die Parameter start und stop auswerten, mit denen /etc/init.d/rc das Skript je nach Situation aufruft. Ein minimales Gerüst für ein solches Skript sieht etwa so aus wie in Listing 2.
Die Kommentare am Anfang bilden den so genannten Init-Infoblock [2]. Ihn werten verschiedene Hilfsprogramme aus. Hinter Provides: steht der Name des Dienstes. Default-Start: nennt die Runlevel, in denen er verfügbar sein soll, Default-Stop: jene, in denen er nicht laufen darf. Hinter Required-Start: stehen die Dienste, die der vorliegende zum Funktionieren benötigt. Anhand dieser Angabe können die Werkzeuge gleich die korrekte Startreihenfolge der Dienste ermitteln. Bei $network handelt es sich um ein spezielles Schlüsselwort, das praktischerweise mehrere Netzwerkdienste zusammenfasst.
Das fertige Skript speichern Sie unter einem passenden Namen (in diesem Fall meindienst) im Verzeichnis /etc/init.d und machen es ausführbar:
chmod 755 /etc/init.d/meindienst
Jetzt fehlen nur noch die passenden Verweise in den Unterverzeichnissen. Die meisten Distributionen bringen ein kleines Werkzeug mit, das diese erzeugt. Unter OpenSuse 11.3 reicht beispielsweise ein insserv meindienst, unter Debian update-rc.d meindienst. Müssen Sie mangels Helfer die Verweise per Hand anlegen, sollten Sie für den Dateinamen eine möglichst hohe Nummer verwenden, wie etwa S99meindienst. Auf diese Weise zerstören Sie nicht die von der Distribution vorgegebene Bootreihenfolge.
Listing 2
###BEGIN INIT INFO
# Provides: meindienst
# Required-Start: $network
# Required-Stop:
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Description: Startet meindienst
###END INIT INFO
#!/bin/bash
case "$1" in
start)
echo "Starte meindienst"
/usr/bin/meindienst &
;;
stop)
echo "Beende meindienst"
killall meindienst
;;
esac
Künftig ohne Siesta
SysV-Init und seine Skripte starten die einzelnen Dienste strikt sequenziell: Erst wenn der zugehörige Prozess seine komplette Einsatzbereitschaft zeigt, darf das nächste Skript anlaufen. Folglich kommt Cups erst an die Reihe, wenn das Netzwerk bereits steht – ähnlich wie im Wartezimmer eines Arztes. Je mehr Dienste starten wollen, desto länger dauert deshalb der gesamte Startvorgang.
Aus diesen Grund steht das betagte SysV-Init bei fast allen großen Distributionen mittlerweile vor der Ausmusterung. Fedora und OpenSuse liebäugeln derzeit mit der Alternative Systemd, Ubuntu setzt schon seit längerem Upstart ein. Beide Nachfolger beschleunigen den Systemstart, indem sie Dienste parallel starten. Wie das genau funktioniert, zeigt der dritte Teil dieser Serie in der nächsten Ausgabe.
Glossar
-
PID
-
Process Identifier. Jeder laufende Prozess (also jedes gestartete Programm) erhält unter Linux eine eindeutige Identifikationsnummer. Diese PID nutzt unter anderem der Befehl
kill.
Infos
[1] Chkconfig: Hans-Georg Esser, “Mit den Dienern reden”, EasyLinux 01/2007, https://www.linux-community.de/Internal/Artikel/Print-Artikel/EasyLinux/2007/01/Mit-den-Dienern-reden
[2] Init-Infoblock: http://wiki.debian.org/LSBInitScripts






