Anwendungen und Prozesse mit Bordmitteln optimal steuern

Aus LinuxUser 11/2007

Anwendungen und Prozesse mit Bordmitteln optimal steuern

Präzise Kontrolle

Auf einem typischen Linux-System laufen viele Anwendungen und Dienste gleichzeitig. Mit den richtigen Befehlen verschaffen Sie sich einen Überblick und greifend steuernd ein.

Auf einem typischen Desktop-System laufen rund 100 bis 200 unterschiedliche Prozesse. Selbst ein einfacher Linux-Server mit Apache als Webserver, Postfix als E-Mail-Server und einigen weiteren Diensten startet 50 bis 100 Prozesse. Deren friedliches Miteinander funktioniert nur aufgrund der ausgeklügelten Mechanismen und Algorithmen, mit deren Hilfe der Kernel den Prozessen Ressourcen zuteilt oder entzieht.

Der Linux-Kernel verfügt über einen leistungsfähigen Prozess-Scheduler und eine ausgereifte Speicherverwaltung, um gestarteten Prozessen Rechenzeit und Speicher zuzuteilen. Ein wählbarer IO-Scheduler bringt Zugriffe auf Massenspeicher in eine geeignete Reihenfolge. Ausgefeiltes Ressourcenmanagement regelt den Zugriff auf Hardwarekomponenten.

Am Anfang

Hat das BIOS den Bootloader und der Bootloader den Linux-Kernel gestartet, initialisiert dieser die zu diesem Zeitpunkt wesentliche Hardware und stößt dann den ersten Prozess namens Init an. Der Init-Prozess wiederum startet über ein komplexes System von Skripten weitere Prozesse, um abhängig vom eingestellten Runlevel einen bestimmten Zustand herzustellen [1]. Die Konfiguration dazu findet sich gewöhnlich in der Datei /etc/inittab auf der Festplatte. Der Einsatz der Runlevel variiert von Distribution zu Distribution. Gewöhnlich dokumentiert die Datei inittab die Details.

Üblicherweise stehen die Runlevel 2 bis 5 für verschiedene Mehrbenutzer-Umgebungen mit oder ohne Netzwerk und grafischer Oberfläche. Runlevel 1 bleibt für den Einzelbenutzer-Betrieb reserviert, etwa für Wartungsarbeiten am System. Runlevel 0 dient gewöhnlich dem Anhalten und 6 dem Neustart des Systems.

Jede Zeile besteht aus vier mit Doppelpunkten voneinander getrennten Spalten (Listing 1, Zeile 9 bis 15). Die erste Spalte enthält einen beliebigen Namen für den Eintrag. In Spalte zwei folgen die Runlevel, in denen Init die in Spalte 3 angegebene Aktion ausführt. Bei der Aktion wait startet Init den in Spalte vier angegebenen Befehl und wartet auf dessen Ende.

Listing 1
# The default runlevel.
id:2:initdefault:
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.
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
# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6

Bei der Aktion respawn (Listing 1, Zeile 20 bis 25) startet Init den Befehl aus Spalte 4 hingegen immer wieder neu, wenn Sie diesen beenden. Mit der Aktion ctrlaltdel (Zeile 18) geben Sie an, was beim Drücken von [Strg]+[Alt]+[Entf] geschieht – in der Regel ein Neustart des Systems. Das funktioniert jedoch normalerweise nur im Textmodus, da der X-Server die Tastenkombination abfängt.

Die Aktion respawn kommt bei den getty-Prozessen zum Einsatz, die die Textkonsolen bereit stellen. Zwischen diesen schalten Sie üblicherweise mit [Alt]+[F1] bis [Alt]+[F6] um. Die Tastenkombination [Alt]+[F7] ist üblicherweise für X11 basierte grafische Oberfläche reserviert, weitere Sitzungen folgen ab [Alt]+[F8]. Möchten Sie von der grafischen Oberfläche aus wechseln, drücken Sie zusätzlich [Strg].

Jedes Terminal hat ein TTY, dessen Gerätedatei (zum Beispiel /dev/tty1) Sie mit dem Befehl tty ermitteln. Bei einer Shell via SSH oder in einem grafischen Terminal-Client wie Xterm, Konsole von KDE oder Terminal von Gnome kommt ein Pseudoterminal wie /dev/pts/1 zum Einsatz.

Die Zeile mit der Aktion initdefault (Listing 1, Zeile 2) gibt den Standard-Runlevel nach dem Booten an. Dort sollte aus naheliegendem Grund weder der Runlevel 0 (Halt) noch der Runlevel 6 (Reboot) stehen. Für jeden der Runlevel startet Init im Beispiel das Skript /etc/init.d/rc mit dem entsprechenden Runlevel als Argument. Das Skript wiederum stößt über ein System mit symbolischen Verweisen weitere Skripte an, die konkrete Dienste in Gang setzen oder stoppen. Die symbolischen Verweise befinden sich bei Debian-basierten Distributionen in den Verzeichnissen /etc/rc0.d bis /etc/rc6.d sowie /etc/rcS.d und bei Suse in /etc/init.d/rc0.d und /etc/init.d/rc6.d sowie /etc/init.d/rcS.d.

Die Namen der Verweise folgen einem Schema: Ein S als erstes Zeichen deutet darauf hin, dass das entsprechende Init-Skript mit dem Argument start losrennt. Bei einem K hingegen kommt ein stop als Argument zum Einsatz. Die darauf folgende, üblicherweise zweistellige Zahl definiert die Reihenfolge, in der die Skripte starten. Mit ls -l verschaffen Sie sich einen groben Überblick in den Verzeichnissen.

Der Befehl who -r zeigt den aktuellen Runlevel, mit init Runlevel wechseln Sie in einen anderen. Speichern Sie jedoch alle wichtigen Daten ab, bevor Sie das ausprobieren. Alternativ halten Sie das System mit shutdown now oder halt an, mit shutdown -r now oder reboot starten Sie es neu. Statt now akzeptiert der Befehl shutdown auch eine andere Zeitangabe.

Was geht?

Einen Überblick darüber, welcher Prozess welche anderen Prozesse startet, verschaffen Sie sich mit Pstree [2]. Der Befehl zeigt in einer Baumstruktur die Kind-Prozesse von Init an. Viele KDE-Anwendungen hängen zum Beispiel von Kdeinit ab, einem Mechanismus, der die Startzeit von KDE-Anwendungen verkürzt (Abbildung 1). Auch der Linux-Kernel startet eigene Prozesse. Dazu verwendet er die Funktion Kthread, die alle weiteren Aktionen anschiebt.

Abbildung 1: Der Befehl Pstree gibt Ihnen eine Übersicht über Prozesse und Kind-Prozesse.

Abbildung 1: Der Befehl Pstree gibt Ihnen eine Übersicht über Prozesse und Kind-Prozesse.

Jeder Prozess hat eine eindeutige Nummer, die Prozess-ID (PID). Mit pstree -p zeigt das Tool diese Information zusätzlich an. Sie erfahren die Prozess-ID eines bestimmten Prozesses auch über die Befehle pidof oder pgrep. Laufen mehrere Prozesse mit gleichen Namen, liefern beide die Nummern aller Prozesse zurück. Übergeben Sie Pstree eine Prozess-ID als Argument, so baut es die Baumstruktur von diesem Prozess aus auf:

$ pstree $(pidof kdeinit)
$ pstree $(pidof kthread)

Eine Liste aller Prozesse erhalten Sie auch mit dem Befehl ps. Gängige Optionen sind u für die Angabe des Benutzers, mit dessen Rechten ein Prozess läuft, x für die Ausgabe von Prozessen ohne TTYs (in der Regel Prozesse der grafischen Oberfläche) oder a zum Anzeigen der Prozesse anderer Benutzer. Die Option f präsentiert eine Baumstruktur ähnlich wie bei Pstree, mit e erfahren Sie die Umgebungsvariablen jedes Prozesses. Die Kombinationen ps aux und ps ef kommen zum Beispiel sehr häufig zum Einsatz.

Interaktiv

Das interaktive Programm Top zeigt eine Liste der Prozesse und aktualisiert diese regelmäßig. Mit [F] wählen Sie ein anderes Sortierkriterium. Mit [U] zeigen Sie nur die Prozesse eines bestimmten Benutzers an. Über [H] gelangen Sie zur (englischsprachigen) Hilfe für die Tastenbefehle. Als Alternative bietet Htop ein via Funktions- und Pfeiltasten steuerbares Menü und das Rollen in der Prozessliste [3].

Abbildung 2: Das Programm Htop zeigt sich in vielen Fällen als eine komfortable Alternative zum altgedienten Top.

Abbildung 2: Das Programm Htop zeigt sich in vielen Fällen als eine komfortable Alternative zum altgedienten Top.

Unter KDE erreichen Sie mit [Strg]+[Esc] jederzeit die Prozessliste des KDE-Systemtools KSysguard. Mit einem Klick auf den Titel einer Tabellenspalte sortieren Sie nach dem entsprechenden Kriterium. Das Gtk-Pendant Gnome-system-monitor schlüsselt zudem via Kontextmenüpunkt Speicherfelder den von einem Prozess belegten Speicher genauer auf. Diese Informationen erhalten Sie auch mit dem Befehl Pmap [4].

Abbildung 3: Der KDE-Systemmonitor KSysguard zeigt sehr übersichtlich die Prozesse auf dem System.

Abbildung 3: Der KDE-Systemmonitor KSysguard zeigt sehr übersichtlich die Prozesse auf dem System.

Ein interaktives Programm eignet sich gut, um schnell herauszufinden, welcher Prozess am meisten Rechenpower oder Speicher beansprucht. Ein fast ununterbrochen laufender CPU-Lüfter in einem Notebook deutet zum Beispiel auf ein Programm hin, das in einer Endlosschleife beständig die freie Rechenzyklen verbraucht.

Prozesse stoppen

Doch wie beenden Sie einen solchen Prozess? Sie senden ihm dazu ein entsprechendes Signal. Es gibt verschiedene Signale, von denen einige eine festgelegte Bedeutung haben. Die Tabelle “Gängige Signale”, das Kommando kill -l sowie Manpage zu Kill liefern entsprechende Details. Darüber hinaus finden sich im Web [5] zusätzliche Informationen.

Gängige Signale

Name Wert Funktion
HUP 1 Hang-Up: Dient häufig dazu, Serverdienste anzuweisen, ihre Konfiguration neu einzulesen
INT 2 Interrupt: Programm anhalten. Identisch zu [Strg]+[C]
KILL 9 Kill: Prozess zwangsweise beenden
SIGV 11 Segmentation Fault: Prozess wegen Speicherschutzverletzung zwangsweise beenden
TERM 15 Terminate: Prozess bitten, sich zu beenden
STOP 19 Stop: Prozess anhalten
TSTP 20 Terminal: Stop. Prozess wie mit [Strg]-[Z] anhalten
CONT 18 Continue: Prozess fortsetzen

Mit kill -SignalPID senden Sie einem Prozess ein Signal. Verwenden Sie dazu am besten den Namen des Signals, um Verwechslungen mit der Prozessnummer zu vermeiden, zum Beispiel: kill -KILL 2222. Geben Sie kein Signal an, sendet kill das Signal TERM. Im Programm Top senden Sie einem Prozess mit [K] ein Signal.

Mit killall oder pkill schicken Sie allen Prozessen mit einem bestimmten Namen oder allen Prozessen eines bestimmten Benutzers ein Signal. Starten Sie mit ping localhost einfach mal einen Prozess und senden Sie ihm zum Testen die verschiedenen Signale (Abbildung 4).

Abbildung 4: Mit definierten Signalen sprechen Sie gezielt einzelne Prozessen an.

Abbildung 4: Mit definierten Signalen sprechen Sie gezielt einzelne Prozessen an.

Wie ein Prozess auf ein Signal reagiert, liegt mehr oder weniger in seinem Ermessen: Das Signal TERM formuliert lediglich eine freundliche Bitte an den Prozess, sich selbst zu beenden. Dagegen macht der Kernel bei KILL im wahrsten Sinne des Wortes kurzen Prozess. Dabei nimmt er keine Rücksicht darauf, ob dieser noch Daten speichern möchte. Setzen Sie daher das Signal nur ein, wenn ein Prozess das System blockiert und nicht mehr anderweitig reagiert.

KDE kennt für das Signal KILL eine Tastenkombination: Mit [Strg]+[Alt]+[Esc] verwandelt sich der Mauszeiger in einen Totenkopf. Dem Prozess mit dem Fenster, auf das sie dann mit der linken Maustaste klicken, sendet KDE das entsprechende Signal. Mit der rechten Maustaste brechen Sie den Vorgang ab. Die Konfiguration dazu finden Sie im Kontrollzentrum gut versteckt unter Regionaleinstellungen & Zugangshilfen | Tastenkürzel | Tastenkombination | Allgemeine Tastenkürzel | Verschiedenes | Fenster beseitigen.

Jobverwaltung

Angenommen, Sie geben einen Befehl ein, der lange läuft, aber kaum oder gar keine Ausgabe am Terminal erzeugt. Löst sich das Programm nicht von der Shell, bleibt diese so lange blockiert. Mit [Strg]+[Z] halten Sie das aufgerufene Programm an. Die Shell nimmt nun neue Befehle entgegen. Ein anderes Beispiel verdeutlicht das Zusammenspiel noch besser: Starten Sie aus einem Terminalfenster ein neues Terminal und in diesem den Befehl ping localhost. Drücken Sie nun im Ursprungsfenster [Strg]+[Z], hält die Ausgabe des Ping-Befehls an. Das zweite Fenster friert komplett ein, wie sie leicht feststellen, wenn Sie ein Objekt darüber hinwegbewegen.

Mit jobs ermitteln Sie in der ersten Shell die gestarteten Jobs. Das Pluszeichen markiert den gerade aktuellen Job. Diesen legen Sie mit dem Befehl bg ohne weitere Argumente in den Hintergrund. Nun läuft der angehaltene Prozess im Hintergrund weiter, während Sie im Vordergrund Befehle eingeben. Mit fg legen Sie ihn wieder in den Vordergrund, um ihn zum Beispiel mit [Strg]+[Z] wieder anzuhalten oder mit [Strg]+[C] abzubrechen. Das Ganze geht auch mit mehr als einem Job. Dazu akzeptieren bg und fg eine Jobnummer als Parameter.

Init-Skripte

Einen Dienst starten und stoppen Sie mit dem dazugehörigen Init-Skript. Es merkt sich in der Regel in /var/run/ in einer Datei mit der Endung .pid die Prozessnummer des laufenden Dienstes. Manche Init-Skripte unterstützten das Neustarten des Dienstes mit restart oder das Neuladen der Konfiguration mit reload oder force-reload. Rufen Sie ein Init-Skript ohne Argument auf, so erhalten Sie meist eine Liste der möglichen Argumente.

Als Suse-Anwender stellen Sie in YaST unter System | Runlevel-Editor ein, welche Dienste das System beim Hochfahren startet. Unter Debian verwenden Sie dazu am besten das Programm Rcconf aus dem gleichnamigen Paket. Beide Werkzeuge erstellen und entfernen die entsprechenden symbolischen Verweise auf das eigentliche Init-Skript in /etc/init.d. Diese Verweise ändern Sie unter Debian auch mit Update-rc.d. Beim Aktualisieren eines Pakets legt dessen Installationsroutine jedoch dann mitunter vorher entfernte symbolische Verweise wieder an. Änderungen mit Rcconf bleiben hingegen erhalten.

Geöffnete Dateien

Haben Sie schon mal vergeblich versucht, eine CD auszuwerfen, da diese noch in Verwendung war? Der Befehl Lsof zeigt eine Liste aller offenen Dateien. Mit lsof Mountpunkt erhalten Sie diese Liste für das entsprechende Dateisystem. Handelt es sich beim Argument nicht um den Mountpunkt, listet Lsof statt dessen exakt, welche Prozesse das angegebene Verzeichnis oder die angegebene Datei geöffnet haben. Mit lsof +D Verzeichnis liefert der Befehl eine Liste aller Prozesse, die das Verzeichnis oder darin befindliche Dateien und Verzeichnisse geöffnet haben.

So finden Sie mit lsof /cdrom oder lsof /media/cdrom schnell hinaus, wer das Auswerfen eines Datenträgers verhindert. Mit lsof -t erhalten Sie nur die Prozessnummern. So beenden Sie mit kill $(lsof -t /cdrom) in einem Rutsch alle Prozesse, die noch auf das eingelegte Medium zugreifen. Schauen Sie jedoch lieber vorher genauer nach, um welche es sich dabei handelt.

Gesprächige Protokolle

Viele im Hintergrund laufende Dienste schreiben Informationen über ihre Aktivitäten oder auftretende Fehler in eine Protokolldatei. Diese finden Sie in der Regel im Verzeichnis /var/log. Meldungen von Diensten nimmt der Syslog-Dienst entgegen. Für die des Kernels zeichnet Klog verantwortlich. Viele Distributionen setzen mittlerweile jedoch Syslog-ng ein, das beide ersetzt.

Die Konfigurationsdateien /etc/syslog.conf beziehungsweise /etc/syslog-ng/syslog-ng.conf legen fest, in welche Datei ein Protokolldienst bestimmte Meldungen schreibt. So landen in /var/log/messages – bei Debian auch /var/log/syslog – üblicherweise die Nachrichten vom Kernel, Kernel-Modulen und grundlegenden Diensten. Einige Dienste, wie Apache, MySQL oder Cups, verwenden dagegen eigene Protokolldateien.

Ein via Cronjob aufgerufenes Programm namens Logrotate benennt jede von ihm verwaltete Datei regelmäßig um und erstellt eine neue, leere Datei. Alte Dateien packt es mit Gzip, um Speicherplatz zu sparen. Protokolldateien mit einem bestimmten Alter löscht es, um Platz auf der Partition zu sparen.

Sie betrachten solche Protokolldateien am einfachsten mit einem Pager, wie Less oder More. Zless arbeitet auf mit Gzip gepackten Daten, während Bzless mit Bzip2 gepackte Dateien darstellt. Der Pager Most hat diese Funktionalität bereits eingebaut. Bei Less rüsten Sie diese bei Bedarf mit eval $(lesspipe) nach. Schreiben Sie diese Zeile in Ihre ~/.bashrc, um die Änderung permanent zu machen.

Manchmal ergibt es Sinn, ein Protokoll live mitzuverfolgen. Mit tail -f Datei bekommen Sie das Ende einer Datei angezeigt. Durch die Option -f wartet der Befehl auf weitere Meldungen, bis Sie [Strg]+[C] drücken. Versuchen Sie dies mit tail -f /var/log/messages oder unter Debian auch mit tail -f /var/log/syslog gleich einmal. Drücken Sie ein paar mal die Eingabetaste, um einige Leerzeilen einzufügen. Verschaffen Sie sich nun mit su in einer anderen Shell Root-Rechte: Sofort taucht die neue Meldung im Protokoll auf (Abbildung 3).

Abbildung 5: Mit dem Befehl     <code srcset=

tail -f beobachten Sie fortlaufend Protokolldateien auf Ihrem System.” width=”300″ height=”126″ /> Abbildung 5: Mit dem Befehl tail -f beobachten Sie fortlaufend Protokolldateien auf Ihrem System.

Viele Server-Dienste erlauben es, die Geschwätzigkeit der Meldungen einzustellen. Funktioniert ein Dienst nicht wie erwartet, und offenbart das Protokoll die Ursache des Fehlers nicht, erhöhen Sie den Umfang des Outputs. Suchen Sie dazu in den Konfigurationsdateien des Dienstes nach den Stichworten log, level, verbose oder verbosity, und ziehen Sie die Dokumentation des Dienstes zu Rate. Vergessen Sie nicht, zum Beispiel mit Hilfe des Init-Skriptes die Konfiguration des Dienstes neu zu laden.

Unter die Haube geschaut

Erfahren Sie auch so nichts über die Fehlerursache, verfolgen Sie mit Strace, welche Systemfunktionen der Prozess aufruft und welche Rückgabewerte diese liefern. So schauen Sie mit strace free an, was das Tool Free alles veranstaltet, um die Speicherauslastung des Systems zu ermitteln und anzuzeigen.

Interessiert Sie nur, welche Dateien der Befehl öffnet, schränken Sie die ausführliche Ausgabe des Befehls mit strace -e trace=open free auf die Systemfunktion open ein. Die Option -e trace=file filtert hingegen alle dateirelevanten, -e trace=process alle prozessverwaltungsbezogenen und -e trace=network alle netzwerkspezifischen Funktionen. Mehrere Angaben trennen Sie mit Komma, zum Beispiel: -e trace=open,close.

Mit der Option -f weisen Sie strace an, Kind-Prozesse zu verfolgen, und mit -v erhalten Sie noch mehr Informationen. Auf einen bereits laufenden Prozess setzen Sie Strace mit der Option -p Prozessnummer an. Und mit strace -o strace.txt landet die Ausgabe des Befehls in einer Datei.

An der Ausgabe von Strace erkennen Sie zum Beispiel leicht, wenn ein Programm eine bestimmte Datei zu öffnen versucht und deshalb nicht startet. In anderen Fällen sind die Ausgaben ohne tiefere Systemkenntnisse allerdings nur schwer verständlich. Dem Entwickler eines Programms helfen sie mitunter jedoch, einen Fehler näher einzugrenzen.

Glossar

Prozess-Scheduler

Teil des Betriebssystems, der laufenden Prozessen Rechenzeit zuteilt. Linux verfügt über einen preemptiven Scheduler, der einen Prozess unterbricht, sobald dieser die ihm zugeteilte Rechenzeit aufgebraucht hat. Durch den schnellen Wechsel zwischen einzelnen Prozessen entsteht der Eindruck, als liefen diese gleichzeitig.

IO-Scheduler

Teil des Betriebssystem, der Lese- und Schreibaufträge an Massenspeicher in eine geeignete Reihenfolge bringt. Der Linux-Kernel unterstützt dabei mehrere Konzepte. Standardmäßig kommt mittlerweile das Completely Fair Queueing (CFQ) zum Einsatz.

Runlevel

Systemzustand, in dem bestimmte Dienste gestartet oder nicht gestartet sind.

TTY

Teletypewriter. Ursprünglich eine Schreibmaschine mit einem elektronischen Kommunikationskanal. Unter Linux Ein- und Ausgabe-Schnittstelle zum Terminal.

Infos

[1] Runlevel bei Wikipedia: http://de.wikipedia.org/wiki/Runlevel

[2] Prozesse beenden: Heike Jurzik, “Kurzer Prozess”, LinuxUser 12/2003, S. 77, http://www.linux-user.de/ausgabe/2003/12/077-zubefehl/

[3] Webseite von Htop: http://htop.sourceforge.net

[4] Grundlagenartikel zum Speichermanagement: http://wiki.debianforum.de/LinuxSpeichermanagement

[5] Signalnamen und Signalnummern: http://strcat.de/eigenes/signale.html

LinuxUser 11/2007 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben