14.6 Initialisierung
Während des Systemstarts werden verschiedene Stufen durchlaufen, für die jeweils Skripte abgearbeitet werden. Diese befinden sich im Systemverzeichnis /etc/init.d/ (siehe auch Abschnitt 14.5, »Dienste«). Auf diese Weise wird die Hardware des Computers schrittweise initialisiert und in Betrieb genommen.
14.6.1 Runlevel
Der Begriff »Runlevel« bezeichnet einen Betriebszustand von Computern. Betriebssysteme durchlaufen beim Start mehrere Systemzustände. Die Reihenfolge, in der die Skripte in den einzelnen Stufen durchlaufen werden, ist in Unterverzeichnissen /etc/rc.Xd abgelegt. Im Einzelnen unterscheidet man die folgenden Runlevel:
- Runlevel 0
Er dient zu Anhalten des Systems bzw. zum kontrollierten Herunterfahren. - Runlevel 1
Hierbei handelt es sich um den Einzelbenutzermodus, es kann also maximal ein Benutzer mit dem System arbeiten. - Runlevel 2–5
Dies sind volle grafische Runlevel mit Multi-User- sowie Netzwerkfähigkeiten. Dies ist mittlerweile der Standard-Runlevel bei modernen Debian- und Ubuntu-Versionen. Zwischen den Runleveln 2–5 werden keine Unterschiede mehr gemacht. - Runlevel 6
Er dient zum Reboot (Neustart) des Systems.
Reboot per Runlevel
Der Übergang in die einzelnen Runlevel kann vom Superuser unter Verwendung des Kommandos init herbeigeführt werden. Loggen Sie sich zu diesem Zweck einmal als Root ein, und versuchen Sie, das System von der Konsole aus neu zu starten: sudo init 6.
Nun können Sie auch einmal versuchen, in den Single-User-Modus via init 1 zu wechseln: Dabei öffnet sich eine Linux-Konsole. Apropos Kommandozeile: Im Multi-User-Modus können Sie jederzeit mittels + + Funktionstaste auf eine Konsole Ihrer Wahl im textbasierten Modus wechseln. , und sind Standardkonsolen, ist die Grafikkonsole. Das ersetzt quasi mehrere Fenster, falls Sie sich im Runlevel 1 oder 3 befinden.
Tipp 218: Runlevel bearbeiten |
Viele erfahrene Linux-Anwender kennen chkconfig. Mit diesem äußerst praktischen kleinen Tool haben Sie direkten Einfluss auf die Runlevel und somit auf die Dienste, die Linux beim Booten startet. Zwar ist dies bei vielen Distributionen auch mit allerlei grafischen Tools möglich, die Geschwindigkeit der schnellen Konfiguration über die Kommandozeile ist damit aber nicht zu erreichen. |
In den Ordnern /etc/rc.d/ bzw. /etc/init.d/ befinden sich nach Runleveln sortiert die symbolischen Links, die das Startverhalten festlegen. Hier reicht es eigentlich, wenn Sie lediglich unerwünschte Links entfernen oder neue hinzufügen. Dadurch werden bestimmte Dienste beim nächsten Start dieses Runlevels entweder ignoriert oder gestartet. Das Tool chkconfig hilft bei der Verwaltung dieser Dienste. |
Bei Ubuntu ist dies Debian-typisch ein bisschen anders. Während OpenSUSE beispielsweise in Runlevel 5 startet, ist es bei Debian-basierten Distributionen Runlevel 2. Aber das ist nicht der einzige Unterschied; Ubuntu kennt beispielsweise standardmäßig das Tool chkconfig nicht. Als Ersatz dafür ist allerdings das Programm sysv-rc-conf über die hauseigene Paketverwaltung installierbar, das die gleichen Aufgaben übernimmt. Die Syntax ist hierbei leicht verändert. Nach der Installation erfolgt die Anzeige aller Dienste als Root über die Option --list: |
sysv-rc-conf --list |
Um einzelne Dienste an- oder abzuschalten, helfen folgende Befehle: |
sysv-rc-conf "Dienst" on |
Nähere Informationen zu sysv-rc-conf erhalten Sie unter http://sysv-rc-conf.sourceforge.net/. |
14.6.2 init
Im vorigen Abschnitt haben Sie kurz die Runlevel kennengelernt, die vom Sys-V-init (init auf System-V-orientierten Systemen) verwaltet werden. Das Sys-V-init wird heutzutage von fast allen UNIX-Systemen verwendet und stellt das standardmäßige Boot-Konzept dar. Genauer gesagt handelt es sich bei Sys-V-init um den Prozess, der als Erstes vom Kernel gestartet wird und daher die Prozess-ID 1 bekommt.
Dieser Prozess startet nun anhand der gewünschten Runlevel die benötigten Systemdienste. Der Ablauf ist fest vorgegeben und normalerweise unter Linux in der Datei /usr/src/linux/init/main.c festgelegt.
Startaufgabe
Die Aufgaben von init sind mannigfaltig. Am Anfang wird init (oder Sys-V-init) vom Kernel gestartet. Dies ist der erste Prozess, und er bekommt folgerichtig die Prozess-ID 1. Init startet nun im User-Space alle weiteren nötigen Prozesse und initialisiert den Rechner. Es werden Kernel-Module geladen, Netzwerke eingerichtet, Dateisysteme gemountet, Serverdienste gestartet und letztendlich der grafische Login-Manager gdm geladen. Dass dies alles in einer vernünftigen Reihenfolge geschehen muss, leuchtet sofort ein, denn zum Beispiel ergibt die Synchronisation der Systemzeit erst Sinn, wenn zuvor die Netzwerkhardware korrekt initialisiert und eingerichtet wurde.
14.6.3 Upstart
Wenn Sie sich die Vorgehensweise von init verinnerlichen (siehe voriger Abschnitt 14.6.2), tritt eine deutliche Schwäche dieses Systems zutage: Aufgrund seiner Konzeption startet Sys-V-init in den Runlevel, ruft die Prozesse immer in einer vorgegebenen Reihenfolge auf und startet einen Prozess meist erst dann, wenn der vorherige Prozess fertig initialisiert wurde und damit abgeschlossen ist. Dieses Schritt-für-Schritt-Vorgehen macht den Boot-Vorgang sehr zuverlässig, aber leider auch relativ langsam. Verantwortlich für diese Vorgehensweise ist Sys-V-init, das im Grunde selbst wiederum ein Dienst ist, und zwar der erste, der auf einem Linux-System vom Kernel gestartet wird. Er bekommt die Prozess-ID 1 und arbeitet sich nun stur durch die Ihnen schon aus dem vorigen Abschnitt bekannten Runlevel.
Modifikationen
Schon seit Längerem gibt es verschiedene Versuche, dieses Konzept zu überarbeiten oder wenigstens zu modifizieren. So gibt es bei einigen Linux-Distributionen (zum Beispiel Gentoo Linux) Umsetzungen, um alle Prozesse in einem Runlevel gleichzeitig starten zu lassen. Diese Modifikationen beschleunigen zwar den Startprozess geringfügig, können aber natürlich bei anderen Problemen, wie zum Beispiel bei wechselnder Hardware im laufenden Betrieb, keine Akzente setzen. Alternativen zu init gab es in der Vergangenheit zuhauf. Beispiele sind hier InitNG, eINIT und Launchd in Mac OS~X der Firma Apple.
Nun ist die Anzahl der zu startenden Dienste aufgrund der Komplexität moderner Hardware und der veränderten Bedürfnisse der Benutzer in den letzten Jahren stetig gewachsen. Von einem Betriebssystem wird heutzutage erwartet, dass es spielend leicht und schnell mit wechselnden Mobilgeräten umgehen kann, wie sie zum Beispiel oft per USB an den Rechner angeschlossen werden. Es muss somit dynamisch seine Systemkonfiguration ändern können.
Ziel vs. Ereignis
Upstart (http://upstart.ubuntu.com) ist der Name eines völlig neuartigen Konzepts, das eine grundlegende Abkehr von init darstellen soll. Die bisherigen Konzepte haben eines gemeinsam: Sie sind zielorientiert. Dies bedeutet, dass vorher festgelegt wird, welche Dienste am Ende des Startvorganges laufen sollen. Die Abhängigkeiten werden vorher in einer sinnvollen Reihenfolge definiert. Upstart hingegen soll ereignisorientiert sein.
Flexibleres Konzept
Jede Job-Datei im Verzeichnis /etc/init ist für den Start eines Dienstes zuständig. Eine feste Reihenfolge gibt es im Gegensatz zu der Vorgehensweise von Sys-V-init nicht mehr. Stattdessen ist in jedem Job definiert, auf welche Ereignisse er wartet und reagieren möchte. Tritt ein Ereignis auf, startet Upstart parallel alle Jobs, die auf dieses Ereignis warten. Bei dieser Vorgehensweise lauern die Dienste im Hintergrund und starten erst dann, wenn alle Vorbedingungen erfüllt sind. Dies sind die sogenannten Events. Beispiel: Wenn Sie einen USB-Stick an den Rechner stecken, löst dies ein Event aus, das dazu führt, dass der USB-Stick gemountet wird.
Klassen
Die Events werden in die folgenden drei Klassen eingeteilt:
- Edge-Events
Dies sind einfache Events wie »Benutzer löst durch Tastendruck eine bestimmte Funktion aus«. - Temporale Events
Dies sind zeitgesteuerte Ereignisse. - Level-Events
Diese Events erhalten einen zusätzlichen Parameter, beispielsweise den Zustand einer bestimmten Hardware. Dienste starten hierbei bei jedem beliebigen Wert oder einem Schwellenwert des Parameters.
Service-Daemon
Upstart soll nicht nur das Booten des Systems beschleunigen, sondern auch das dynamische Verwalten von Diensten. Dies betrifft folgende Bereiche, die mit Upstart vereinheitlicht und verwaltet werden sollen:
- Viele Dienste hängen vom Funktionieren bestimmter Hardware ab. So können manche Dienste erst gestartet werden, wenn die dazu nötige Netzwerkverbindung ad hoc aufgebaut wurde.
- Die Dynamik der Diensteverwaltung betrifft auch zeitabhängige Prozesse. So gibt es Services wie Cron oder den Anacron, die bestimmte Prozesse zu festgelegten Zeitpunkten starten.
Vorsichtige Umstellung
Die Entwicklung ist noch nicht abgeschlossen, die erste Implementation dieses neuen Konzeptes hat 2006 Einzug in Ubuntu gehalten. Temporale Events sind zwar noch nicht integriert, aber seit der Version Ubuntu 9.10 (erschienen im Oktober 2009) sind viele Skripte auf Upstart umgestellt. Etliche Systemeinstellungen und Daemon-Aufrufe wurden inzwischen auf Upstart umgestellt, darunter das Einbinden der Laufwerke, der Start von Udev und Cron sowie der grafischen Oberfläche. Allerdings ist man noch nicht so weit, gänzlich auf die alten Init-Skripte verzichten zu können.
So funktioniert Upstart
Das erste Ereignis, startup, erzeugt Upstart beim Aufruf selbst. Start und Ende jedes Jobs sind weitere Ereignisse, nämlich started Jobname und stopped Jobname, und werden ebenfalls erzeugt. Auf das Ereignis startup warten mehrere Jobs, darunter der Job hostname zur Einrichtung des Rechnernamens; die zugehörige Job-Datei ist hostname.conf und unter /etc/init/ zu finden.
Das Ereignis start on bewirkt, dass dieser Job gestartet wird. Gibt es mehrere Ereignisse, auf die der Job reagieren soll, so müssen diese durch and oder or logisch miteinander verknüpft werden.
Das Ereignis start on darf nicht mehrfach vorkommen. Das bedeutet, dass der Job zu einem späteren Zeitpunkt beendet wird, indem Sie per stop on zusätzliche Stop-Events definieren, bei denen der Job abgearbeitet wird. Welches Programm der Job aufruft, steht hinter dem Schlüsselwort exec.
Tipp 219: Startanalyse |
Der Systemstart von Ubuntu erfolgt recht zügig. Testmessungen zeigen Boot-Zeiten im Bereich von unter 30 Sekunden. Zur Auswertung eignet sich das Tool Boot chart (siehe Abbildung 14.4), das Sie über die Quellen von Ubuntu bekommen (Paketname bootchart). Dieses Messwerkzeug protokolliert während des Startvorgangs in einem Takt von 0,2 Sekunden die CPU-Auslastung sowie die Platten-IO-Leistung und speichert die grafische Darstellung in dem Ordner /var/log/Bootchart/. Hier werden alle Protokolle eindeutig bezeichnet und im PNG-Format abgelegt. |
Abbildung 14.4 Die Abbildung zeigt eine Boot-chart-Analyse eines Ubuntu GNU/Linux 12.04, das mit »Upstart« hochfährt. Der Beispielrechner benötigt knapp 26 Sekunden vom Starten des Kernels bis zum grafischen Login-Manager.
Tipp 220: Eigene Skripte beim Booten ausführen |
Sie können Ubuntu anweisen, eigene Skripte beim Booten auszuführen. Dazu ändern Sie eine Zeile der Grub-Konfigurationsdatei. Öffnen Sie diese mit: |
sudo gedit /etc/default/grub |
Fügen Sie anstelle von quiet splash die Verknüpfung zu Ihrem Skript ein. |
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" |
Starten Sie anschließend Ihren Rechner neu. |
Ereignisse als Schlüssel
Das ereignisgesteuerte Konzept unterscheidet sich grundlegend von dem chronologischen Abarbeiten der Runlevel. Upstart ist sehr viel flexibler. Besteht beispielsweise beim Start der Zeitsynchronisation über das Internet noch keine Netzwerkverbindung, muss bei dem alten Sys-V-init der Timeout abgewartet werden. Somit steht das System während des Bootens kurze Zeit still. Bei der Vorgehensweise von Upstart hingegen wird diese Synchronisation erst dann gestartet, wenn die Netzwerkverbindung steht. Das zugehörige Start-Ereignis lautet network up. Dadurch, dass es keine feste Reihenfolge der Jobs gibt und diese parallel auf Ereignisse warten, kann ein System mit Upstart wesentlich schneller booten als eines mit Sys-V-init.
Getty
Anhand der Konfigurationsdatei /etc/init/tty1.conf können Sie die Ereignisorientierung besser nachvollziehen. Dieser Job ist zuständig für den Start des Terminalemulators getty für die Textkonsole 1.
1 # tty1 - getty
2 #
3 # This service maintains a getty on tty1 from the point the system is
4 # started until it is shut down again.
5
6 start on stopped rc RUNLEVEL=[2345]
7 stop on runlevel [!2345]
8
9 respawn
10 exec /sbin/getty -8 38400 tty1
Hier sehen Sie, dass die exec-Anweisung (Zeile 10) erst dann ausgeführt wird, wenn eines der vorher mit start on definierten Ereignisse eintritt (Zeile 6). Analog wird getty wieder beendet, sobald ein Ereignis mit stop on eintritt (Zeile 7). Wenn das Programm ungeplant beendet wird, bewirkt respawn einen Neustart von getty (Zeile 9).
respawn
Mit dem zusätzlichen Schlüsselwort respawn wird Upstart angewiesen, den Prozess immer wieder neu zu starten, wenn er sich beendet. Dies kann selbstverständlich zu einer Überlastung des Systems führen. Um dies zu verhindern, lässt sich mit der Option limit begrenzen, wie oft Upstart über welchen Zeitraum versuchen soll, den Dienst zu starten; so lautet beispielsweise der Befehl für einen dreimaligen Versuch innerhalb von 60 Sekunden:
respawn limit 3 60
Zusätzlich gibt es die Schlüsselwörter pre-start und post-start, mit denen Befehle unmittelbar vor und nach dem Start eines Dienstes ausgeführt werden können, etwa um notwendige Verzeichnisse anzulegen oder nach dem Start des Dienstes bestimmte Systemeinstellungen anzupassen. Da exec erwartet, dass der Dienst im Vordergrund startet, kann Upstart mit der Ausführung von post-start nicht warten, bis der Dienst beendet wurde. Deshalb führt Upstart post-start parallel mit dem Start des Dienstes aus.
In den bisherigen Beispielen wurden Befehle stets unmittelbar per exec aufgerufen. Anstelle von exec kann jedoch auch ein Befehlsblock gesetzt werden, der von den Schlüsselwörtern script und end script eingeschlossen wird:
pre-start script
if [ ! -e /var/run/tserv ]; then
mkdir -p /var/run/tserv
fi
end script
Kommandos
Ein großer Unterschied zwischen Upstart und Sys-V-init ist, dass in den Init-Skripten Dienste immer als Daemon im Hintergrund laufen und somit von der Konsole abgekoppelt sind, weil ansonsten das Init-Skript blockiert würde, bis der Dienst beendet ist. Durch die Abkoppelung kann Init aber nur mit erheblichem Aufwand feststellen, ob ein Dienst läuft oder sich beendet hat. Init gelingt dies nur, 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.
Upstart hingegen erwartet, dass der hinter exec genannte Prozess im Vordergrund läuft – denn nur so lange, wie 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.
Wenn im Verzeichnis /etc/init eine entsprechende Konfigurationsdatei liegt, starten oder beenden die Befehle start bzw. stop einen Prozess. Der Befehl status gibt den aktuellen Zustand des Prozesses an.
Prozesse beenden
Beim Stoppen eines Jobs kümmert sich Upstart ausschließlich um den per exec im Vordergrund gestarteten Prozess. Er sendet ihm das Terminate-Signal (SIGTERM) und erwartet, dass er sich selbst beendet. Beendet sich der Prozess nicht, wird er wenige Sekunden später mittels Kill-Signal (SIGKILL) hart abgebrochen.
Tipp 221: Linux-Jobs |
Aktive Programme werden unter Linux Jobs genannt. Sie starten ein Programm im Hintergrund, wenn Sie an den entsprechenden Befehl ein & hängen. Wenn Sie dies einmal vergessen sollten, können Sie mit der Tastenkombination + das Programm manuell anhalten. Mit den Befehlen fg und bg können Sie das Programm nun im Vordergrund bzw. im Hintergrund weiterarbeiten lassen. |
Möchten Sie wissen, wann ein lange laufendes Programm sich beendet, können Sie es (wie wir bereits wissen) mit + anhalten und dann mit folgendem Befehl wieder starten: |
fg ; while /bin/true; do echo -ne a; sleep 1; done |
Nachdem nun das Programm beendet ist, wird in einer Endlosschleife ein Piepgeräusch erzeugt. |
Tipp 222: Boot-Skripte parallel ausführen |
Während des Startens Ihres Betriebssystems werden mehrere Skripte ausgeführt, die ihrerseits wiederum notwendige Dienste im Hintergrund aufrufen. Standardmäßig werden diese Skripte nacheinander ausgeführt, damit Ubuntu auch auf älteren (Single-Core-)Rechnern zuverlässig startet. Ein moderner PC hat allerdings inzwischen meistens einen Prozessor, in den mehrere Prozessorkerne integriert sind. Wenn der Boot-Vorgang nur einen Prozessorkern beansprucht, werden die anderen eventuell vorhandenen Kerne allerdings nicht genutzt. Einerseits ist dies eine Verschwendung von Ressourcen, andererseits können Sie durch das parallele Ausführen der Skripte wertvolle Zeit beim Booten sparen. |
Um das parallele Ausführen zu aktivieren, öffnen Sie die notwendige Konfigurationsdatei: |
sudo gedit /etc/init.d/rc |
In Zeile 33 finden Sie folgenden Eintrag: |
CONCURRENCY=none |
Ändern Sie diesen Eintrag in CONCURRENCY=shell. |
Im Übrigen befinden sich im Ordner /var/log/boot zahlreiche Log-Informationen. Generell gehen die Ausgaben der Upstart-Skripte an den in Upstart enthaltenen logd, der die Informationen im genannten Verzeichnis speichert. Upstart kennt aus Gründen der Kompatibilität mit dem Init-V-System auch Runlevel. Diese sind allerdings als Ereignisse mit den Namen runlevel n definiert.
Das Kommando runlevel zeigt Ihnen den aktuellen Runlevel an. Einen neuen Runlevel aktivieren Sie mit telinit n. Administrative Aufgaben werden mit initctl erledigt. Mittels initctl list verschaffen Sie sich einen Überblick über alle laufenden Prozesse.
Fazit
Die Boot-Zeiten eines modernen Linux-Systems haben sich teilweise drastisch reduziert. Ubuntu hat die Zeit zum Starten des Systems mittlerweile nahezu halbiert – auch dank Upstart. Auf einem modernen Rechner benötigt das System gerade noch rund 20 Sekunden. Hierbei ist die Fahnenstange noch lange nicht erreicht: Boot-Zeiten von einigen wenigen Sekunden sind das Ziel. Wer Upstart aber nur auf das Booten des PCs beschränkt, tut dem Projekt Unrecht. Upstart ist auf dem guten Weg dahin, immer mehr die Aufgabe eines zentralen Service-Daemons zu übernehmen.
Ihr Kommentar
Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.