UNIX Prozesse
Willemers Informatik-Ecke
Ein Prozess ist der Begriff für ein gestartetes Programm.

Hintergrundbearbeitung und Reihenfolge

Durch Anhängen von & an ein Kommando wartet die Shell nicht auf auf das Ende des Programms, sondern lässt es im Hintergrund arbeiten. Dabei wird an der Konsole noch die Prozess-ID angezeigt, unter der der Prozess gestartet wurde. Im Beispiel unten wird das Programm xman in den Hintergrund gestartet. In der eckigen Klammer wird angezeigt, dass es bereits das zweite Programm ist, das so gestartet wurde. Der neue Prozess erhält die Prozess-ID 3717. Wird das Hintergrundprogramm irgendwann beendet, erscheint auch darüber eine Meldung auf der Konsole. Wieder wird die Jobnummer angezeigt und mit >>Done<< (engl. getan) angezeigt, dass das Programm xman fertig ist.

gaston> xman &
[2] 3717
gaston>
...
gaston>
[2]+  Done                    xman
gaston>

Prozessbeobachter

Man kann den Prozess betrachten, indem man den Befehl jobs angibt. Leider wird dieser Befehl von der Bourne Shell nicht unterstützt. Aber der Befehl ps ohne Optionen zeigt die Liste der gestarteten Prozesse.

Zwei Prozesse nacheinander

Wenn man mehrere Befehle hintereinander in einer Kommandozeile abgeben will, verwendet man als Trenner das Semikolon. Die folgende Eingabe zeigt also erst die Dateien an und dann das Datum:

ls; date

Durch Anhängen eines & werden die beiden Prozesse nacheinander im Hintergrund ausgeführt. Das zweite Programm wartet also mit seinem Start bis das erste Programm fertig ist. Sollen die Programme parallel laufen, schickt man beide einzeln in den Hintergrund.

gaston> ls &
gaston> date &

Terminalausgaben

Beim Starten der Prozesse in den Hintergrund kann man beobachten, dass beide Programme ihre Ausgabe direkt auf den Bildschirm schreiben, von dem sie gestartet wurden. Da man im Allgemeinen Prozesse im Hintergrund nicht am Bildschirm beobachten will, sollte man die Ausgabe in eine Datei umleiten.

Voneinander abhängige Prozesse

Sollen zwei Programme nacheinander ausgeführt werden, tut man dies normalerweise, weil ein Programm auf den Ergebnissen eines anderen aufbaut. In solchen Fällen ist es aber sinnlos, das zweite Programm auszuführen, wenn bereits das erste scheiterte. Auch hierfür gibt es eine Lösung. Programme unter UNIX geben an die Shell ihren Erfolgsstatus in Form einer Fehlernummer zurück. Ist diese 0, ist alles in Ordnung. Durch ein doppeltes kaufmännisches Und, also && wird das zweite Programm nur gestartet, wenn das erste Programm 0 zurückgab.

programm1 && programm2

Auch das Gegenteil ist möglich: Durch die Verwendung zweier senkrechter Striche wird programm2 nur ausgeführt, wenn programm1 scheiterte.

programm1 || programm2

Klammern bewirken eine eigene Subshell

Durch Klammern eingeschlossene Kommandos werden in einer eigenen Subshell gestartet. Auf diese Weise lassen sich Kommandos bündeln. Da die Shell die Rückmeldung der zuletzt gestarteten Programme an den Aufrufer weiterleitet, kann man auch in den logischen Abfolgen klammern.

Hier eine Übersicht, wie mehrere Programme gestartet werden können:

Syntax Ausführung
prog1 ; prog2 Erst prog1, dann prog2 ausführen
prog1 && prog2 prog2 nur bei Erfolg von prog1 ausführen
prog1 || prog2 prog2 nur bei Misserfolg von prog1 ausführen

Prioritäten: nice

Priorität reduzieren

Der Befehl nice kann einen Prozess auf niedrigere Priorität setzen, damit andere Prozesse in ihrer Ausführung nicht so stark gestört werden. Spötter behaupten, es sei der unter UNIX am seltensten benutzte Befehl. Dabei ist die Benutzung extrem einfach: vor das Kommando schreibt man einfach das Wort nice. Man kann den Grad seiner Nettigkeit sogar beziffern, sie kann maximal bei 19 liegen. Je höher der Wert, desto netter ist der Anwender, weil er die Priorität seines Prozesses zugunsten anderer Prozesse senkt. Gibt man seine Freundlichkeit nicht explizit an, ist sie 10. Nur root darf seine Nettigkeit in negativen Zahlen ausdrücken und darf dabei bis -20 gehen. Einige Systeme vermeiden die negativen Zahlen, indem sie den Wertebereich von 0 bis 39 festlegen.

Um einen Prozess im Nachhinein in seiner Priorität zu verändern, gibt es das Programm renice. Das ist praktisch, wenn man einen Prozess in den Hintergrund gestellt hat, der soviel Aufmerksamkeit der Maschine erfordert, dass man nicht mehr im Vordergrund arbeiten kann.

Ausloggen bei laufendem Prozess: nohup

Wenn man einen Prozess mit & in den Hintergrund stellt und sich anschließend ausloggt, erhält dieser Prozess ein Signal namens SIGHUP. Dies führt, wenn der Programmierer es nicht explizit abfängt, normalerweise zum Abbruch des Programms. Um das Senden des Signals zu verhindern, gibt es den Befehl nohup, den man dem Befehl einfach voranstellt. Dadurch wird das Programm von SIGHUP nicht mehr belästigt und man kann sich problemlos ausloggen.

Automatische Umleitung

Bei der Verwendung des Befehls nohup ist abzusehen, dass das Terminal für Ausgaben nicht zur Verfügung stehen wird. Die Ausgabe des Prozesses, die normalerweise auf das Terminal geht, wird in die Datei nohup.out umgeleitet. Falls der Prozess im aktuellen Pfad kein Schreibrecht hat, wird die Datei im Heimatverzeichnis abgelegt.

Prozessliste anzeigen: ps

Auch die Prozessabhängigkeiten bilden einen Baum

Der Befehl ps zeigt eine Prozessliste. Ohne Parameter zeigt er die Liste der eigenen Prozesse der aktuellen Sitzung. Das ist im allgemeinen die Shell und ps selbst. Wurden in der Sitzung Prozesse in den Hintergrund gestellt, die noch laufen, erscheinen diese auch. Interessant an dieser Liste ist die PID. Das ist die Prozess-ID, die für jeden Prozess eigen ist. Verwendet man für ps den Parameter -l, dann sieht man diverse Informationen mehr über die Prozesse. Dabei gibt es eine PPID (Parent Process ID), die die PID des Elternprozesses ist. Der Vaterprozess ist derjenige Prozess, von dem ein Prozess gestartet wurde. Man kann erkennen, dass der Vater des ps die Shell ist. Es gibt einen Baum von Prozessen, der mit dem init-Prozess beginnt. Dieser hat immer die PID 1.

gaston> ps -l
UID   PID  PPID  PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
501  1292  1291   69   0 -   711 wait4  pts/0    00:00:00 bash
501  3578  1292   69   0 -   931 do_sel pts/0    00:00:03 vi
501  3598  3597   70   0 -   712 wait4  pts/2    00:00:00 bash
501  3634  3598   69   0 -  1984 do_pol pts/2    00:00:02 ggv
501  3658  3634   69   0 -  2770 do_sel pts/2    00:00:03 gs
501  3807  3598   77   0 -   749 -      pts/2    00:00:00 ps
gaston>

In der Prozessliste sind zweimal die Shell bash zu erkennen, einmal mit der PID 1292, das andere mal mit der PID 3598. Die erste Sitzung ist der Vater eines vi. Die zweite Sitzung ist einmal der Vater von ggv, der selbst wieder Vater von gs ist, und dann der Vater des ps. Man kann daraus schließen, dass ggv vor Aufruf des ps in den Hintergrund gestartet wurde.

Man kann noch sehr viel mehr Details erkennen, wie die CPU-Zeit, die der Prozess bereits verbraucht hat, das Kommando, das ausgeführt wurde, von welchem Terminal der Prozess gestartet wurde und einige Dinge mehr.

Dies ist der Grund, warum man unter UNIX niemals ein Passwort oder etwas Geheimes als Kommando absetzen darf. Durch ps kann jeder andere Benutzer der Maschine den vollständigen Befehl lesen.

Fremde Prozesse

Neben den eigenen Prozessen, kann man auch die Prozesse anderer Benutzer sehen. Dazu gibt man -alx oder -elf an. Je nach System funktioniert der eine oder das andere Parameter. Danach rauschen alle Prozesse des Systems auf dem Bildschirms vorüber, was man durch eine Pipe nach more natürlich verhindern kann. Wichtig zu wissen ist, dass man auf einem UNIX-System jede Aktivität beobachten kann. Dadurch ist ein Fehlverhalten des Systems, sowie amoklaufende Prozesse und Prozesse unbekannter Herkunft leicht identifizierbar.

Wenn die Ausgabezeilen von ps länger sind als der Bildschirm anzeigen kann, schneidet ps leider den Rest der Zeile ab. Um dies zu verhindern kann mit der Option w die Zeile zum Umbruch (w wie wrap - englisch Umbruch) gebracht werden. Bei einigen älteren Unixsystemen muss die Option w unter Umständen wiederholt werden. ps -axwww zeigt so wirklich alles an, was man über Prozesse wissen will.

Mit der Option -u wie User wird zusätzlich auch noch der Eigentümer des jeweiligen Prozesse angezeigt.

Die Option -w (w wie wrap) bricht die einzelnen Zeilen der Prozessliste am Zeilenende um. Das normale Verhalten von ps ist es, die Ausgabe am rechten Bildschirmrand abzuschneiden. So verliert man aber leicht die Informationen, die über den rechten Rand hinausragen.

Stoppen eines Prozesses: kill

Hat man einen Prozess in den Hintergrund gestellt, möchte ihn aber doch wieder vorzeitig stoppen, kann man dies mit dem Kommando kill erreichen. Als Parameter gibt man die Prozess-ID des zu eliminierenden Prozesses an.

Lizenz zum Töten

Man darf nur eigene Prozesse abschießen. Lediglich der Administrator ist berechtigt, auch fremde Prozesse zu töten. Die meisten UNIX-Programme sind so geschrieben, dass sie ihre Daten sichern und einen regulären Abgang durchführen, wenn sie einen normalen kill empfangen. Sollte ein kill also nicht sofort Erfolg zeigen, kann das damit zu tun haben, dass der Prozess noch mit den Terminierungstätigkeiten beschäftigt ist. Ein zweiter kill ist da selten hilfreich. Nach etwa fünf Sekunden sollten die Prozesse aber dann terminieren. Soviel Zeit gibt ihnen der Shutdown auch, bevor er weitergeht. Hartnäckige Prozesse schießt man mit einem kill -9 ab.

Programmabbruch

Programmende durch ctrl-C

Ein gestarteter Prozess kann meist mit ctrl-C abgebrochen werden. Auf älteren Systemen wurde dazu die Delete-Taste verwendet. Der im Vordergrund laufende Prozess erhält dadurch das Terminierungssignal SIGINT und beendet sich regulär.

Programmunterbrechung durch ctrl-Z

Es gibt bei vielen UNIX-Systemen die Möglichkeit, einen Prozess auch kurzfristig anzuhalten. Allerdings muss auch die Shell dies unterstützen. Dazu drückt man ctrl-Z und erzeugt damit das Signal SIGTSTP. Es erscheint die Meldung, dass der Prozess gestoppt worden ist.

[1]+  Stopped (user)          xemacs libash.htm

In der rechteckigen Klammer steht die Jobnummer aus Sicht der Shell, in diesem Fall eine 1. Diese Nummer darf nicht mit der PID verwechselt werden. Mit dem Befehl jobs wird die Liste der Jobs angezeigt. Auf diese Nummer wird mit den Kommandos fg, bg und kill referenziert, indem ein Prozentzeichen vorangestellt wird. Man kann den Job im Vordergrund fortsetzen, indem man

fg %1

eingibt. Damit hat man die Situation vor dem ctrl-Z wieder hergestellt. Das kann Sinn machen, wenn man kurz das Terminal für andere Zwecke benötigte. Um den gestoppten Job im Hintergrund weiterlaufen zu weiterlaufen zu lassen, gibt man den Befehl bg ein.

bg %1

Das macht vor allem Sinn, wenn man einen Prozess aus Versehen ohne & gestartet hatte und er nun die Konsole blockiert. Man sollte aber vorsichtig sein, die frei gewordene Konsole zum Ausloggen zu verwenden, da das bg-Kommando nicht nachträglich das nohup-Kommando setzt.

Letztendlich kann man den zunächst gestoppten Job auch töten.

kill %1

Insbesondere beim kill ist es wichtig, das %-Zeichen vor der Zahl nicht zu vergessen, da diese die Jobnummer und nicht die PID bezeichnet. Das Verfahren funktioniert nicht bei allen UNIX-Varianten, da das Signal SIGSTP benötigt wird, welches nicht in jedem UNIX verfügbar ist. Auch die Shell muss mitspielen. Die Korn-Shell und die bash von LINUX und Solaris 8 unterstützen es.

Diese Seite basiert auf Inhalten aus dem Buch Arnold Willemer: Wie werde ich UNIX-Guru?