Prozessverwaltung

Allgemeines

Jedes gestartete Programm auf dem System ist ein Prozess. Manche Programme erzeugen sogar mehrere Prozesse. Init ist immer auf einem Unixsystem der erste beim booten vom Kernel gestartete Prozess. Wird aus einem Prozess heraus ein neuer Prozess gestartet, spricht man von einem Kindprozess des ersten Prozesses. Letztendlich sind also alle Prozesse Kindprozesse von Init. Startet man selbst einen Prozess aus einer Shell heraus, ist der Prozess immer auch ein Kindprozess der laufenden Shell.

Beendet sich ein Elternprozess wird automatisch auch jeder Kindprozess beendet. Passiert dies einmal nicht, wird der Kindprozess der nun verwaist ist zum sogenannten "Zombie". Zombies können nicht mehr beendet werden, da ihnen der kontrollierende Elternprozess fehlt. Sie belegen etwas Arbeitsspeicher, machen aber ansonsten nichts. Sie verschwinden meistens erst nach einem Reboot. Möchte man einen Kindprozess bis zu seinem Laufzeitende auch bei fehlenden kontrollierenden Elternprozess weiter laufen lassen, kann man den Befehl nohup verwenden. nohup sorgt dafür, daß jeder Prozess der mit nohup gestartet wurde, Beendigungssignale seines Elternprozesses (im allgemeinen also der Shell von der der Prozess aufgerufen wurde) ignoriert und einfach bis zu seinem "natürlichen" Ende weiterläuft.

nohup make

Dieser Befehl sorgt dafür das der make-Befehl auch bei Beendigung des Terminals weiterläuft. Ausgaben des Befehls landen dann in der Datei nohup.out. Dies kann bei längeren Kompilierprozessen die remote auf einer anderen Maschine ausgeführt werden, praktisch sein, da man sich während der Kompiliervorgang weiter läuft, einfach abmelden kann.

Mit dem kaufmänischen Und-Zeichen "&", kann man Prozesse im Hintergrund starten. Dadurch erhält man seinen Kommandoprompt sofort wieder zurück, während das Kommando im Hintergrund weiter läuft. Sinnvoll ist dies natürlich nur bei länger laufenden Befehlen. Außerdem werden alle Ausgaben des Befehls weiterhin auf das Terminal ausgegeben. Möchte man dies verhindern, kann man gleichzeitig eine Ausgabeumlenkung in eine Datei definieren:

make > output 2>&1 &

Dieser Befehl startet den make-Prozess im Hintergrund und gibt alle Ausgaben sowohl der Standardausgabe, als auch der Standardfehlerausgabe in die Datei output aus. Näheres zur Ausgabeumlenkung, zu Hintergrundprozessen, sowie auch zur Jobkontrolle findet sich in den Unterlagen zu Shell und Shellscripting.

ps

Mit dem Kommando ps kann man sich alle laufenden Prozesse anzeigen lassen. Gibt man nur ps ein, erhält man eine sehr kurze Ausgabe, denn ohne weitere Parameter zeigt ps nur die eigenen Prozesse im aktuellen Terminal an, was im allgemeinen nur die Shell und der ps-Prozess selbst ist:

$ ps
  PID TTY       TIME CMD
22524 pts/0 00:00:00 bash
22551 pts/0 00:00:00 ps

Die Spalte PID gibt dabei die Prozess-ID an. Jeder Prozess im System besitzt eine einmalige Nummer, die zwischen 1 und 65536 liegen kann. Die PID ist diese Nummer. In der Spalte TTY wird angegeben in welchen kontrollierenden Terminal (falls es eines gibt) der Prozess läuft. Das hier zu sehende pts-Terminal ist ein Pseudo-Terminal, welches für Terminals innerhalb von X oder Terminals für Netzwerklogins (z. B. mit SSH) verwendet wird. Mit Time wird die benutzte Prozessorzeit angegeben. In der letzten Spalte steht der Prozessname selbst.

Mit dem Parameter a zeigt ps auch Prozesse die anderen Benutzern gehören, mit dem Parameter x auch Prozesse die nicht in einem kontrollierenden Terminal laufen (z. B. Hintergrunddienste). Parameter können beim ps Kommando auch ohne führendes Minuszeichen angegeben werden:

ps ax

Mit diesem Kommando erhält man also alle Prozesse auf dem laufenden System. Die hierbei zusätzlich ausgegebene Spalte STAT zeigt den Status eines Prozesses an, wie etwa S für sleeping oder R für running.

Noch mehr Informationen erhält man mit dem zusätzlichen Parameter u:

ps aux

Die Ausgabe von ps wird nun um noch weitere Spalten ergänzt. Unter anderem findet sich als erste Spalte der Benutzer unter dem der Prozess läuft. Ergänzt wurde auch der Startzeitpunkt des Prozesses (START) und auch der Speicherverbrauch des Prozesses (%MEM).

Möchte man genauer wissen welche Prozesse Kindprozesse welcher anderen Prozesse sind, kann man den Befehl pstree verwenden. Sollte bei Ihnen der Aufruf von pstree in einem Command not found enden, ist dieser Befehl wahrscheinlich bei Ihrer Linuxdistribution bzw. Ihrem Unixsystem nicht im Standardumfang der Installation enthalten und sie müssen es über Ihren Paketmanager nachinstallieren. pstree zeigt Kind- und Elternprozesse in einer Baumartigen Struktur an.

top

Während man mit ps eine Momentaufnahme des Systems bekommt, liefert der Befehl top eine ständig aktualisierte Liste der Vorgänge im System. top ist ein interaktiver Befehl, der so lange läuft bis er mit "q" (für quit) beendet wird. Mit top kann ich sozusagen dem System beim arbeiten zusehen.

Welche Informationen von top in den Kopfzeilen angezeigt werden, unterscheidet sich von Unixvariante zu Unixvariante ein wenig. Ich werde hier die Variante von Linux beschreiben, die meisten anderen Unixartigen Systeme zeigen ähnliche, wenn auch nicht ganz die gleichen Informationen an.

In der ersten Zeile von top findet sich von Links nach Rechts: Die Uhrzeit, die Zeit seit dem Systemstart, die Anzahl der eingeloggten Benutzer und die durchschnittliche Systemlast in den letzten 5, 10 und 15 Minuten. Die Zahlen für die Systemlast meinen dabei jeweils 1.0 für den Fall das eine CPU vollständig ausgelastet ist. Ein Einprozessorsystem ist also mit einer Systemlast von 1.0 vollständig ausgelastet, ein 2-Prozessorsystem hingegen mit einer Systemlast von 2.0. Die gleichen Angaben erhält man auch durch das Kommando uptime.

Die zweite Zeile in top liefert einige Angaben zu den Prozessen im System: die Gesamtzahl aller laufenden Prozesse, die Zahl aller Prozesse im Status running, die Zahl aller schlafenden Prozesse, die Zahl aller gestoppten Prozesse und die Zahl aller Zombies.

Die dritte Zeile in top liefert die Prozessorauslastung. Das Kürzel id steht dabei für idle, also wieviel Prozent der CPU gerade nichts tut. us steht für User, also wieviel Systemlast Userlandprozesse verbrauchen. sy steht für System, also wieviel Systemlast Kernelprozesse verbrauchen und ni steht für nice, das heißt wieviel Prozent der Systemlast durch genicete Prozesse (siehe nächster Abschnitt) verbraucht werden.

Die vierte Zeile gibt die Menge des Speicherverbrauchs an. Die erste Spalte zeigt die Gesamtmenge an physischen Arbeitsspeicher an, danach kommt wieviel davon derzeit in Benutzung ist. Linux neigt in seiner Speicherverwaltung dazu möchlichst viel vorhandenen Speicher auch tatsächlich zu nutzen, da ungenutzter Speicher verschwendeter Speicher ist. Das heißt natürlich das ein fast vollständig genutzter Speicher keineswegs bedeutet, das der Rechner mehr Ram bräuchte. Erst wenn auch Swap mitgenutzt wird, ist es wirklich an der Zeit den Rechner mit mehr Ram zu bestücken.

Die letzte Kopfzeile in top gibt schließlich die Nutzung von Swap (also Auslagerungsspeicher) an.

Unterhalb dieser Kopfzeilen findet sich die Liste der laufenden Prozesse. Die Anzeige dieser Liste kann auch interaktiv beeinflußt werden. Möchte man z. B. nur die Prozesse eines bestimmten Benutzers sehen, tippt man "u" und man wird nach dem Benutzernamen gefragt. Läßt man das Feld leer werden alle Benutzer angezeigt (was der Default ist), ansonsten tippt man einen Benutzernamen ein und drückt Enter. Möchten sie die angezeigten Felder der Prozesse in top verändern geht dies auch: Drücken sie "f". Die Anzeige verändert sich nun. Sie sehen eine Übersicht über die angezeigten und anzeigbaren Felder. Alle Felder die mit einem Stern beginnen werden angezeigt. Sie können durch drücken der entsprechenden Buchstaben für die Felder diese aktivieren oder deaktivieren. Mit Return kommen sie wieder in die Prozessanzeige zurück. top hat darüber hinaus eine sehr ausführliche Manpage, in der man weiter Kniffe im Umgang mit top erfahren kann.

Prozesspriorität

Alle Prozesse auf einem Unixsystem können in ihrer Priorität verändert werden. Dazu gibt es sogenannte Nice-Level. Diese lassen sich mit den beiden Kommandos nice und renice setzen. Nice-Level gehen von -20 bis 19, wobei -20 die höchste Priorität ist (nicht etwa die niedrigste). Der normale Nice-Level eines Prozesses ist 0. Normale Benutzer können die Nice-Level ihrer Prozesse nur verringern (also höher als 0 einstellen), lediglich root kann den nice-Level eines Prozesses auch auf negative Werte verändern um höhere Prioritäten zu erreichen.

nice -n 15 make

Dieses Kommando startet den Befehl make mit einem Nice-Level von +15, also einer sehr niedrigen Priorität. Dies kann nützlich sein, um einen Kompiliervorgang im Hintergrund auszuführen ohne das dabei andere Prozesse zu sehr gestört werden. Der Parameter -n dient zur Angabe des Nice-Levels. Der Name nice kommt davon das man "nett" ist zu den anderen Prozessen im System, also die Priorität verringert.

nice sox 15-Der_mit_dem_Wolf_tanzt.mp3 -C 5 \
15-Der_mit_dem_Wolf_tanzt.ogg

Dieser Befehl startet das Kommando sox (zur Audiokonvertierung) mit einem nice-Level von 10, damit ich gleichzeitig diese Zeilen ohne Verzögerung im vi tippen kann (ja, das führe ich im Moment so aus). Gibt man bei nice keinen Nice-Level mit dem Parameter -n an wird ein Nice-Level von +10 als Default verwendet.

Ist ein Prozess bereits gestartet und man möchte nachträglich den Nice-Level verändern, läßt sich der Befehl nice nicht nutzen. Dafür gibt es den Befehl renice.

renice +5 1098

Dieses Kommando setzt den Nice-Level des Prozesses mit der PID 1098 auf +5. Per Default gibt man bei renice die PID eines Prozesses an, der verändert werden soll. Die PID kann man z. B. mit dem Kommando ps in Erfahrung bringen. Es ist aber auch möglich alle Prozesse eines bestimmten Users zu verändern:

renice -10 -u root

Mit diesem Befehl werden alle momentan laufenden Prozesse des Benutzers root auf einen Nice-Level von -10 gesetzt (also eine recht hohe Priorität. Dieser Befehl kann natürlich nur von root ausgeführt werden. Der Parameter -u verlangt einen Benutzernamen dessen Prozesse verändert werden sollen.

Signale

Signale beeinflussen Prozesse. Meistens verwendet man Signale um Prozesse zu beenden (killen). Das Kommando um Signale zu senden, hat daher auch seinen Namen: kill.

kill -l

Mit diesem Befehl (Kleinbuchstabe l, nicht die 1) werden alle verfügbaren Signalnamen und Nummern ausgegeben. Die meisten davon wird man wahrscheinlich nie benötigen. Wichtige Signale sind z. B.: 15 SIGTERM zum normalen beenden von Prozessen und 9 SIGKILL zum beenden von Prozessen die sonst nicht mehr reagieren. Der Unterschied zwischen SIGTERM und SIGKILL, liegt darin das SIGTERM eine Aufforderung an den Prozess ist sich zu beenden. Was der Prozess mit diesem an ihn gesendeten Signal am Ende aber wirklich macht, bleibt ihm überlassen. Bei SIGKILL hingegen sorgt das Betriebssystem selbst dafür, daß der Prozess beendet wird. SIGKILL sollte man daher nur im Notfall verwenden, da der Prozess dadurch keine Möglichkeit mehr hat nötige Aktionen vor dem Beenden auszuführen, wie etwa temporäre Dateien löschen oder ähnliches.

Generell interpretiert jeder Prozess ein Signal selber. Das heißt es bleibt dem Prozess selbst überlassen wie er auf ein Signal reagiert. SIGKILL ist dabei eine Ausnahme da hier das Betriebssystem und nicht der Prozess selbst aktiv wird.

Das Signal SIGHUP (1) wird auch noch häufig benutzt. Eigentlich steht es dafür das sich ein Prozess beenden soll, weil die kontrollierende Shell, bzw, das Terminal sich beendet hat. HUP steht für hangup, also ein Auflegen der Leitung, was noch aus Analogmodemzeiten stammt. Häufig wird dieses Signal jedoch auch benutzt um Servern, die als Hintergrundprozess laufen (und sowieso kein kontrollierendes Terminal haben), zu sagen das sie ihre Konfiguration neu einlesen sollen. Dies verstehen nicht alle Serverdienste um man sollte vorher in der Dokumentation des jeweiligen Programms nachsehen, ob das Signal so verstanden wird. Der OpenSSH-Server ist ein Beispiel für einen Dienst der das Signal so versteht.

kill -1 3607

In diesem Beispiel wird das Signal Nr. 1 (also SIGHUP) an den Prozess mit der pid 3607 geschickt. Die PIDs der Prozesse lassen sich über ps heraus finden. Es lassen sich sowohl Signalnamen, als auch die Nummern bei kill angeben. Wird nur eine PID und gar kein Signal angeben, wird als Default das Signal 15 SIGTERM verwendet.

Wie man sieht benötigt man recht oft die PID eines Prozesses. Man kann natürlich einfach die Ausgabe von ps über grep filtern um vom Prozessnamen an dessen Nummern zu gelangen:

ps ax | grep dhcpd

Es gibt jedoch bereits ein solches Kommando vorgefertigt: pgrep:

pgrep dhcpd

Dieses Kommando sucht alle PIDs heraus von Prozessen die im Prozessnamen dhcpd enthalten. Weiß man ohnehin das man dem entsprechenden Prozess ein bestimmtes Signal schicken will, kann man auch pkill verwenden:

pkill -9 httpd

Dieses Kommando schickt an alle Prozesse deren Prozessname httpd enthält das SIGKILL Signal. Seien sie beim Einsatz dieses Befehls aber vorsichtig: Manchmal ist es besser vorher zu prüfen, welche Prozesse diese Zeichen im Namen enthalten um nicht auch Prozesse zu stoppen, die man eigentlich gar nicht stoppen wollte (stellen sie sich vor neben dem Prozess mit Namen httpd läuft auch noch einer mit dem Namen "controlscript --check httpd").


René Maroufi, dozent (at) maruweb.de
Creative Commons By ND