Jobs

Die Bash, das unbekannte Wesen

01.12.2000
Es gibt neben den Pipes noch verschiedene andere Verfahren, um mehrere Shell-Befehle miteinander zu verbinden bzw. sie parallel auszuführen. Die wichtigsten Methoden werden in dieser Folge der Bash-Serie vorgestellt.

Ein Überblick

Wie im letzten Teil beschrieben, können mit Befehlsfolgen viele Aufgaben unter Linux einfach und schnell via Pipes erledigt werden. Die Bash als Multitasking-Programm ist aber ebenfalls in der Lage, gleichzeitig mehrere Prozesse, sogenannte "Hintergrund-Jobs", zu verwalten und zu kontrollieren.

Ein Hintergrundjob entsteht durch das "Ablösen" eines Prozesses vom kontrollierenden Terminal. Normalerweise können einem beliebigen Programm von dem Terminal aus, von dem es gestartet wurde, Signale zugesendet werden. Ein einfaches Beispiel: Ein lange andauernder sort-Befehl kann - wie die meisten anderen Befehle - durch [Strg]-[c] beendet werden. Viele Programme können andere Signale empfangen und interpretieren. So wird etwa der init-Prozeß (oder auch xinit) durch das SIGHUP-Signal (HUP: hang up "auflegen") veranlaßt, seine Konfigurationsdatei erneut einzulesen. Viele weitere Programme (aber nicht unbedingt alle) reagieren so auf dieses Signal. Es wird mittels des kill-Befehls an die entsprechenden Prozesse gesendet.

#>kill -1 1

In diesem Beispiel wird durch -1 das SIGHUP-Signal ausgewählt und mit 1 die PID (Process Idenfitfication Number) des Zielprozesses (hier: init) festgelegt. Normalerweise muß dessen PID zunächst ermittelt werden. Entweder wird dafür der ps-Befehl eingesetzt, oder pidof (Process ID of running programm):

    
 $> #>ps
  PID TTY TIME CMD
...
  329 tty2 00:00:00 bash
  346 tty2 00:00:00 startx
  347 tty2 00:00:00 tee
  356 tty2 00:00:00 xinit
  360 tty2 00:02:20 kwm
  663 tty2 00:00:22 kfm
  666 tty2 00:00:05 krootwm
  671 tty2 00:01:22 kpanel
  672 tty2 00:00:07 kbgndwm
  677 tty2 00:01:00 kvt
...

In der ersten Spalte dieser Ausgabe stehen die PIDs. Dem Systemverwalter steht mit pidof ein komfortabler (aber wesentlich gefährlicherer) Befehl zur Ermittlung von PIDs zur Verfügung:

#pidof xinit
356

pidof kann gewöhnlich nur vom Systemverwalter ausgeführt werden, da es sich bei dem Programm um einen Link auf /sbin/killall5 handelt.

Nachdem die PID des gewünschten Prozesses bekannt ist, kann diesem das erforderliche Signal zugesandt werden. Dazu wird der kill-Befehl eingesetzt. Ein kurzer Blick auf die Online-Hilfe zeigt die Syntax:

    
$> help kill
kill: kill [-s sigspec | -n signum | -sigspec] [pid | job]... or
kill -l [sigspec]
    Send the processes named by PID (or JOB) the signal SIGSPEC.  
    If SIGSPEC is not present, then SIGTERM is assumed. ...

Hier sind einige Anmerkungen zu kill angebracht. Zunächst einmal, warum wird die Online-Hilfe mit help aufgerufen und nicht wie üblich mit der Option -help? Die Bash verfügt über einen internen kill-Befehl, für den die Online-Hilfe (wie für alle eingebauten Befehle, mehr dazu im nächsten Teil dieser Reihe) durch help aktiviert wird. Dieser eingebaute Befehl wird immer verwendet, wenn nicht die externe Befehlsvariante durch Angabe des Pfades (üblicherweise /bin/kill) explizit aufgerufen wird. Für unsere Zwecke ist der eingebaute kill-Befehl aber genau richtig. Als nächstes betrachten wir die Optionen von kill: -s erwartet als Argument den Namen eines Signals, voreingestellt ist SIGTERM, das zum unbedingten Programmende führt und durch [Strg]-[C] erzeugt wird. Durch -n kann die Angabe der Signale numerisch erfolgen, ebenso wie durch ein einfaches vorangestelltes Minuszeichen. Diese Eigenschaft wurde in dem init-Beispiel oben ausgenutzt. Als nächstes Argument muß entweder die PID des Zielprozesses angegeben werden oder eine Job-Nummer. Zu den Jobs kommen wir gleich. Alternativ kann kill mit der Option -l (list signals) aufgerufen werden:

    
 
$> kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     17) SIGCHLD
18) SIGCONT     19) SIGSTOP     20) SIGTSTP     21) SIGTTIN
22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO
30) SIGPWR      31) SIGSYS  

Diese Option bewirkt, dass kill die verfügbaren Signale sowohl numerisch als auch mit ihren Namen ausgibt, so wie der Befehl sie als Argumente der Option -s versteht. Das erste Beispiel hätte also wie folgt geschrieben werden können:

    
#kill -s SIGHUP 1

Die tatsächliche Wirkung eines Signals hängt von dem empfangenden Programm ab. Ihre üblichen Funktionen werden in [2] beschrieben. Nur wenige Programme reagieren auf alle Signale, und wenn sie eines interpretieren, ist die Funktion nicht immer genau vorhersehbar. Hier hilft ein Blick in die Dokumentation des Programms. Einige Signale haben aber immer dieselben Funktionen: Mit SIGTERM wird ein Programm "zwangsweise, aber vorschriftsgemäß" beendet, durch SIGKILL wird es "gnadenlos abgewürgt". Im ersten Fall kann das Programm noch aufräumen, also beispielsweise temporäre Dateien löschen, Verbindungen zu anderen Prozessen ordnungsgemäß beenden und ähnliches. Dazu bleibt im zweiten Fall keine Gelegenheit mehr, diese Variante (kill -9 ...) sollte also wirklich nur in Ausnahmesituationen angewendet werden. Die Signal-Voreinstellung mit SIGTERM hat übrigens zu dem Programmnamen "kill" geführt.

Mit den Signalen bietet die Bash eine einfache Möglichkeit, laufende Prozesse "von außen" zu beeinflussen. So richtig spannend wird dies, wenn Hintergrund-Jobs mit ins Spiel kommen.

Befehle im Hintergrund ausführen

Bisher wurden Befehle auf der Bash immer direkt ausgeführt. Die Shell hat das entsprechende Programm geladen, die Ein- und Ausgabekanäle mit dem Terminal verbunden und sich um die Ressourcen beim Programmablauf gekümmert. Die Konsequenz daraus war, das die Shell bis zum Ende des auszuführenden Programms gesperrt war. Heute ist dies nicht mehr ganz so schlimm, kann der Anwender bei Bedarf doch einfach ein neues virtuelles Terminal unter X öffnen und dort weiterarbeiten. Neben einem völlig unnötigen Ressourcenverbrauch führt dies aber schnell zu einem wenig übersichtlichen Destop. Daher bieten alle modernen Shells die Möglichkeit, laufende Programme "im Hintergrund ausführen zu lassen".

Die einfachste Art, einen Befehl im Hintergrund auszuführen, bietet die Bash mit dem "&"-Operator (Ampersand-Zeichen). Befehlszeilen, die mit diesem Zeichen enden, werden automatisch im Hintergrund ausgeführt. Dabei verliert das Programm teilweise die Verbindung zu dem Terminal, auf dem es gestartet wurde. Es kann keine Eingaben (oder Signale) mehr von dort empfangen. Ausgaben kann das Programm aber noch an das Terminal senden, wie folgendes Beispiel zeigt:

    
 $>
$> ls -R /&
[1] 31886
$> ls -l
/:
bin   cdrom  etc     home  lost+found  opt   root  tmp  var
boot  dev    floppy  lib   mnt         proc  sbin  usr
insgesamt 45
-rw-r-r-  1 work  users   10030 Oct  2 17:54 #bash-jobs.tex#
-rw-r-r-  1 work  users      48 Oct  2 17:36 bash-jobs.aux
-rw-r-r-  1 work  users   10136 Oct  2 17:36 bash-jobs.dvi
-rw-r-r-  1 work  users    8517 Oct  2 17:36 bash-jobs.log
-rw-r-r-  1 work  users   10021 Oct  2 17:45 bash-jobs.tex
...

Die ersten drei Zeilen stammen dabei von ls -R, die folgenden wurden durch ls -l erzeugt. Im Hintergrund laufende Prozesse werden als "Jobs" bezeichnet.

Eine andere Möglichkeit für Hintergrund-Jobs ist die folgende: Auch bereits laufende Programme können "in den Hintergrund geschickt" werden, um das Terminal für andere Aufgaben zu verwenden. Ein typisches Beispiel sieht folgendermaßen aus: Sie starten ein Programm und merken dann, dass einige Einstellungen falsch oder unvollständig waren. In vielen Fällen können Sie nun das Programm einfach durch die Tastenkombination [Strg]+[z] anhalten, die notwendigen Dateien kopieren (oder was immer erforderlich ist) und das Programm weiter laufen lassen. Soll es das Terminal, von dem aus es gestartet wurde, wieder freigeben, werden Sie es durch bg ("background")im Hintergrund laufen lassen. Mit fg ("foreground") können derartig laufende Programme erneut in den Vordergrund geholt (mit dem Terminal verbunden) werden. Eine Übersicht aller im Hintergrund einer Shell laufenden Programme gibt Ihnen der Befehl jobs:

    
$> jobs
[2]-  Running   xv &
[3]+  Stopped   man bash

Die Ausgabe von jobs kann durch einige Optionen modifiziert werden: -l bewirkt, dass der Befehl auch die PIDs der laufenden Prozesse anzeigt, durch -p werden nur diese dargestellt. Mit -n zeigt jobs nur solche Jobs an, deren Status sich seit dem letzten Aufruf verändert haben, die also von "schlafend" zu "laufend" gewechselt haben, o. ä. -r zeigt nur die aktiven (laufenden: "running") Jobs an, -s nur die schlafenden. Ein beliebiger Befehl kann durch jobs mit den Jobnummern als Argument ausgeführt werden:

    
$> jobs -x kill %2
[2]- Exit 1       xv  

In diesem Beispiel wird die Jobnummer (%2) anstelle der PID an den kill-Befehl übergeben. Oft ist diese Methode übersichtlicher als die Verwendung der PIDs, zumal nur auf die Jobs der lokalen Shell zugegriffen werden kann und alle anderen Prozesse so vor Fehlern geschützt sind. Der eingebaute kill-Befehl der Bash verfügt übrigens per sè über die Fähigkeit, Prozesse via Jobnummern identifizieren zu können.

Eine besondere Situation tritt bei lange laufenden Jobs auf. Wenn sich der User abmeldet, werden normalerweise alle von ihm initiierten Jobs beendet, indem die Shell das Signal SIGHUP an diese Prozesse sendet. (Schlafende Prozesse werden zuvor mittels SIGCONT geweckt.) Angenommen, Sie rechnen ein kompliziertes Modell, vielleicht rendert PovRay Ihnen gerade eine Grafik, dann müssen Sie aber nicht bis zum Ende der Berechnungen eingeloggt bleiben (und Ihr Terminal bewachen). Es gibt zwei Möglichkeiten, lange laufende Jobs vor dem Beenden beim Logout zu schützen.

Variante eins setzt auf einen speziellen Befehl mit dem Namen nohup (für "no Hang Up"). Diesem Befehl wird eine Befehlszeile als Argument übergeben, die nach dem Logout weiter ausgeführt werden soll. nohup fängt dann SIGHUP-Signale (und auch SIGTERM, SIGINT sowie SIGQUIT) ab, die die Shell an das in der Befehlszeile enthaltene Programm schickt. Als erstes versucht der Befehl aber eine Ausgabedatei für mögliche Meldungen und Ausgaben durch die in der Befehlszeile enthaltenen Befehle zu öffnen. Normalerweise wird dazu die Datei nohup.out im aktuellen Verzeichnis erzeugt. Gelingt dies nicht, versucht nohup diese Datei im Home-Verzeichnis des Anwenders anzulegen. Ist auch dies nicht möglich, terminiert der Befehl ohne die Befehlszeile auszuführen. Die GNU-Variante dieses Befehls läßt sich leicht modifizieren, da es sich um ein kleines Script handelt.

    
$> nohup lange-laufendes-Programm &
$> logout

Zwei Anmerkungen zu nohup: Der Befehl bewirkt nicht, dass die übergebene Befehlszeile im Hintergrund ausgeführt wird, daher sollte die Befehlszeile mit dem Ampersand-Zeichen abgeschlossen werden. Auch sollte berücksichtigt werden, dass nohup die übergebene Befehlszeile mit einer (etwas) verringerten Priorität ausführt (Nice-Wert von "5"), sich die Bearbeitungszeit also verlängert, wenn hier nicht mit renice gegengesteuert wird.

Variante zwei nutzt ein spezielles Feature der Bash. Mit dem eingebauten Befehl disown können gezielt einzelne Hintergrund-Jobs in der Job-Tabelle so markiert (versteckt: hide) werden, dass sie für bestimmte Signale nicht mehr erreichbar sind. Durch die Option -h wird verhindert, dass dem entsprechenden Job ein SIGHUP-Signal gesendet werden kann.

Eine weitere Besonderheit ist beim Einsatz von Jobs zu beachten. Mit der unter Linux üblichen GNU-Variante des Terminal-Konfigurationsbefehls stty können durch die Option tostop alle Hintergrund-Jobs automatisch angehalten werden, wenn Sie versuchen, auf ein Terminal zu schreiben. (Solange Sie diesen Versuch nicht unternehmen, laufen die Prozesse ganz normal.)

    
$> stty tostop   aktiviert die Funktion
$> stty -tostop  deaktiviert sie wieder

LinuxCommunity kaufen

Einzelne Ausgabe
 
Abonnements
 

Ähnliche Artikel

  • Bash-Kurs Teil 6
    Die elementaren Konfigurationsmöglichkeiten mit eingebauten Funktionen der Bash sind der Schwerpunkt dieses Teils. Im nächsten wird ein komfortables Tool zur Erzeugung von Konfigurationsdateien vorgestellt.
  • Die Bash, das unbekannte Wesen
    Die Leistungsfähigkeit einer Shell ist nur zum Teil durch die komfortablen Möglichkeiten bei der interaktiven Bedienung begründet. Mindestens genauso wichtig sind die "inneren Werte" einer Shell, also die eingebauten Befehle, die Funktionen zur Bearbeitung von Variablen, Skripten und Funktionen sowie anderen Features.
  • Shell-Tipps
    Erfahrene Linux-Nutzer schwören auf flexible Kommandozeilentools, mit denen sich manche Aufgabe schneller bewältigen lässt als in grafischen Programmen. Wir stellen die wichtigsten Anwendungen vor, um auch Einsteiger zu einem Ausflug in die Shell zu ermutigen.
  • Tricks für die Bash
    Mit ein paar grundlegenden Kniffen bringen Sie Schwung und Farbe in die Arbeit auf der Kommandozeile.
  • Shortcuts für die Bash
Kommentare

Infos zur Publikation

LU 12/2014: ANONYM & SICHER

Digitale Ausgabe: Preis € 4,95
(inkl. 19% MwSt.)

Mit der Zeitschrift LinuxUser sind Sie als Power-User, Shell-Guru oder Administrator im kleinen Unternehmen monatlich auf dem aktuelle Stand in Sachen Linux und Open Source.

Sie sind sich nicht sicher, ob die Themen Ihnen liegen? Im Probeabo erhalten Sie drei Ausgaben zum reduzierten Preis. Einzelhefte, Abonnements sowie digitale Ausgaben erwerben Sie ganz einfach in unserem Online-Shop.

NEU: DIGITALE AUSGABEN FÜR TABLET & SMARTPHONE

HINWEIS ZU PAYPAL: Die Zahlung ist auch ohne eigenes Paypal-Konto ganz einfach per Kreditkarte oder Lastschrift möglich!       

Tipp der Woche

Ubuntu 14.10 und VirtualBox
Ubuntu 14.10 und VirtualBox
Tim Schürmann, 08.11.2014 18:45, 0 Kommentare

Wer Ubuntu 14.10 in einer virtuellen Maschine unter VirtualBox startet, der landet unter Umständen in einem Fenster mit Grafikmüll. Zu einem korrekt ...

Aktuelle Fragen

Nach Ubdates alles weg ...
Maria Hänel, 15.11.2014 17:23, 4 Antworten
Ich brauche dringen eure Hilfe . Ich habe am wochenende ein paar Ubdates durch mein Notebook von...
Brother Drucker MFC-7420
helmut berger, 11.11.2014 12:40, 1 Antworten
Hallo, ich habe einen Drucker, brother MFC-7420. Bin erst seit einigen Tagen ubuntu 14.04-Nutzer...
Treiber für Drucker brother MFC-7420
helmut berger, 10.11.2014 16:05, 1 Antworten
Hallo, ich habe einen Drucker, brother MFC-7420. Bin erst seit einigen Tagen ubuntu12.14-Nutzer u...
Can't find X includes.
Roland Welcker, 05.11.2014 14:39, 1 Antworten
Diese Meldung erhalte ich beim Versuch, kdar zu installieren. OpenSuse 12.3. Gruß an alle Linuxf...
DVDs über einen geeigneten DLNA-Server schauen
GoaSkin , 03.11.2014 17:19, 0 Antworten
Mein DVD-Player wird fast nie genutzt. Darum möchte ich ihn eigentlich gerne abbauen. Dennoch wür...