Job-Control ist die Fähigkeit der Bash, mehrere Prozesse gleichzeitig im selben Terminal zu verwalten — pausieren, in den Hintergrund schicken, wieder hervorholen. Wer &, jobs, fg, bg und Ctrl + Z beherrscht, braucht für viele Aufgaben kein zweites Terminalfenster mehr. Das Konzept stammt aus den frühen Unix-Tagen und ist bis heute ein zentrales Werkzeug für effizientes Arbeiten auf der Kommandozeile.

Was Job-Control ist

Die Bash kann mehrere Prozesse gleichzeitig im selben Terminal verwalten. Ein Prozess kann entweder im Foreground laufen — dann blockiert er die Eingabe und bekommt Tastatur-Input direkt zugestellt — oder im Background, wo er ohne Interaktion weiterarbeitet und das Terminal frei lässt. Die Steuerung dieser Modi nennt man Job-Control.

Wichtig zu unterscheiden: Ein Job ist nicht dasselbe wie ein Prozess. Ein Job ist ein Bash-internes Konzept und kann aus einer ganzen Pipeline mehrerer Prozesse bestehen. Startest du cat log | grep ERROR | wc -l &, ist das ein einziger Job mit drei Prozessen. Die Bash verwaltet Jobs über fortlaufende Job-Nummern (%1, %2, …), der Kernel kennt diese Nummern nicht — er sieht nur die einzelnen Prozesse und ihre Process Group ID (PGID).

Job-Control ist standardmäßig in jeder interaktiven Bash-Sitzung aktiv. In nicht-interaktiven Skripten ist sie meistens deaktiviert; mit set -m lässt sie sich dort einschalten.

Im Hintergrund starten — &

Hängst du an einen Befehl ein & an, startet die Bash ihn im Background. Das Terminal bleibt sofort frei, du kannst weiterarbeiten. Die Bash gibt dabei die Job-Nummer und die PID aus.

Bash Build im Hintergrund starten
make &
Output
[1] 12453

Die Ausgabe [1] 12453 heißt: Job-Nummer 1, PID 12453. Klassischer Einsatz ist alles, was lange läuft und keine Tastatureingabe erwartet — Builds, Konvertierungen, Downloads, lokale Server. Sobald der Background-Job endet, meldet die Bash das beim nächsten Prompt mit [1]+ Done make.

Pause und Resume

Ein laufender Foreground-Prozess lässt sich mit Ctrl + Z pausieren. Die Bash schickt dem Prozess das Signal SIGTSTP (Terminal Stop), der Prozess geht in den Zustand T (Stopped) und du bekommst sofort den Prompt zurück. Der Job ist nicht beendet, sondern eingefroren — sein Speicher, seine offenen Dateien und sein Zustand bleiben erhalten.

Aus diesem Pausenzustand gibt es zwei Wege zurück:

  • bg setzt den Job im Background fort (er läuft weiter, aber das Terminal bleibt frei)
  • fg holt ihn als Foreground-Job zurück (du landest wieder in der Anwendung)

Im Hintergrund weckt die Bash den Job mit dem Signal SIGCONT. Mehr zu Signalen und ihrer Wirkung im Artikel Signale unter Linux.

jobs

Der Befehl jobs listet alle Jobs der aktuellen Shell mit ihrem Status auf — typischerweise Running, Stopped oder Done.

Bash Aktive Jobs anzeigen
jobs
Output
[1]   Running                 make &
[2]-  Stopped                 vim notes.md
[3]+  Running                 npm run dev &

Das + markiert den current job, das - den previous job. Diese Kennzeichnungen sind keine Spielerei: Sie sind die Grundlage der Job-Specs, mit denen du Jobs gezielt ansprechen kannst.

Job-SpecBedeutung
%1, %2, …Job mit der angegebenen Nummer
%% oder %+Current Job (zuletzt im Foreground oder per bg/fg angesprochen)
%-Previous Job (der vorherige Current Job)
%vimJob, dessen Befehlszeile mit dem Namen beginnt
%?errorJob, dessen Befehlszeile den String enthält

Mit jobs -l werden zusätzlich die PIDs angezeigt, mit jobs -p nur die PIDs — praktisch, wenn du sie an kill oder ein Skript weitergeben willst.

fg und bg

fg holt einen Job in den Foreground, bg setzt einen gestoppten Job im Background fort. Beide akzeptieren eine Job-Spec; ohne Argument wirken sie auf den Current Job (%%).

Bash Job-Steuerung
fg %1          # Job 1 in den Vordergrund holen
bg %2          # Job 2 im Hintergrund fortsetzen
fg             # Current Job zurückholen
fg %vim        # Job zurückholen, der mit "vim" beginnt

fg ist der schnellste Weg zurück in einen pausierten Editor: einmal Ctrl + Z, etwas erledigen, dann fg und du bist wieder mittendrin. bg braucht man, wenn ein Befehl versehentlich ohne & gestartet wurde — Ctrl + Z plus bg ist die Rettung.

Job vs. Prozess vs. PGID

Drei Begriffe, die leicht verwechselt werden:

BegriffWer kennt es?Was ist es?
Jobnur die Bashinterne Nummer (%1) für eine Pipeline oder einen einzelnen Befehl
Prozessder Kerneljede laufende Programminstanz mit eigener PID
PGIDder KernelProcess Group ID — fasst alle Prozesse eines Jobs zusammen

Wenn du cat log | grep ERROR | wc -l & startest, entstehen drei Prozesse mit drei PIDs, aber alle drei haben dieselbe PGID — die PID des ersten Prozesses (cat). Die Bash merkt sich diese PGID intern und ordnet ihr die Job-Nummer zu.

Daraus folgt ein praktischer Trick: Mit kill -- -PGID (das führende Minus markiert eine Prozessgruppe) erlegst du den ganzen Job-Verbund mit einem Schlag. Details und weitere Signal-Optionen im Artikel kill und Prozesse beenden.

Praxis-Patterns

Die folgenden Muster decken die meisten Alltagsfälle ab. Jeder Block kommt mit einer kurzen Erklärung, wann und warum er nützlich ist.

Build im Hintergrund starten — der klassische Einsatz von &. Während der Build läuft, bleibt das Terminal nutzbar; der Exit-Status wird beim nächsten Prompt gemeldet.

Bash Make im Hintergrund
make &

Editor pausieren, Shell-Befehl, zurückkehren — der häufigste Job-Control-Workflow überhaupt. Statt ein zweites Terminal zu öffnen, parkst du den Editor kurz und kommst danach genau dort zurück, wo du warst.

Bash Editor pausieren und zurückkehren
vim README.md
# Ctrl + Z pausiert vim
git status
fg

Mehrere Builds parallel und auf alle wartenwait ohne Argument blockiert, bis alle Background-Jobs fertig sind. So lassen sich unabhängige Schritte sauber parallelisieren.

Bash Parallele Builds
make backend &
make frontend &
wait
echo "alle Builds fertig"

Job per Name fortsetzen — wenn mehrere Jobs laufen, ist der Name oft eindeutiger als die Nummer.

Bash Job über Namen ansprechen
fg %vim

Job killenkill versteht Job-Specs direkt, du musst keine PID nachschlagen.

Bash Job per Job-Spec beenden
kill %1

Output beim Background-Start umleiten — ohne Umleitung schreiben Background-Jobs weiter ins Terminal und stören jede Eingabe. Mit > log 2>&1 & landet stdout und stderr in einer Datei.

Bash Sauber im Hintergrund mit Logging
long-running-task > task.log 2>&1 &

Stolperfallen

Ein einzelnes & ist nicht &&

cmd1 & cmd2 startet cmd1 im Hintergrund und führt sofort cmd2 aus — egal ob cmd1 erfolgreich war. cmd1 && cmd2 dagegen wartet auf cmd1 und startet cmd2 nur, wenn der Exit-Code 0 war. Die Verwechslung ist ein Klassiker; ein vergessenes zweites & kann ganze Pipelines durcheinanderbringen.

Background-Jobs schreiben weiter ins Terminal

Wenn du einen Befehl mit & startest, läuft seine Ausgabe trotzdem weiter ins aktuelle Terminal — mitten in deine nächste Eingabe. Lösung ist immer dieselbe: stdout und stderr umleiten, also cmd > log 2>&1 &. Wer das routinemäßig macht, hat sauberere Sessions und kann die Logs später bequem nachlesen.

Terminal zu — Jobs sterben

Schließt du das Terminal-Fenster oder beendest die Login-Sitzung, schickt der Kernel ein SIGHUP an alle Prozesse der Session. Background-Jobs sterben dabei mit. Wer länger laufende Aufgaben terminalunabhängig braucht, nutzt nohup, disown oder einen Terminal-Multiplexer — siehe nohup und disown.

set -m schaltet Job-Control ein

In nicht-interaktiven Bash-Skripten ist Job-Control standardmäßig aus. Befehle wie fg und bg funktionieren dort nicht, und Background-Jobs laufen ohne eigene Process Group. Mit set -m lässt sich Job-Control auch in Skripten aktivieren — nötig zum Beispiel, wenn man Subshells gezielt mit kill -- -PGID beerdigen will.

wait ohne Argument wartet auf alle

wait allein blockiert die Shell, bis alle Background-Jobs fertig sind. Mit wait %1 wartest du nur auf einen bestimmten Job, mit wait $! auf den zuletzt gestarteten. Praktisch, wenn ein Skript mehrere Tasks parallel startet und am Ende ihre Exit-Codes auswerten soll.

Pipeline mit & ist EIN Job

cmd1 | cmd2 | cmd3 & ergibt einen einzigen Job mit drei Prozessen, nicht drei Jobs. Die Bash gibt nur eine Job-Nummer aus, und kill %1 beendet alle drei Prozesse über ihre gemeinsame Process Group. Wer einzelne Glieder einer Pipeline gezielt beenden will, muss mit PIDs arbeiten — die Job-Spec greift immer den ganzen Verbund.

Tab schliessen sendet SIGHUP

Tab-Close, Window-Close oder das Beenden der SSH-Verbindung lösen alle dasselbe Verhalten aus: Die kontrollierende Shell beendet sich, und der Kernel schickt allen Mitgliedern der Session ein SIGHUP. Nur Jobs, die per disown aus der Job-Liste entfernt oder per nohup gegen SIGHUP gepanzert wurden, überleben das.

disown loest Jobs vom Terminal

disown %1 entfernt den Job aus der Bash-Job-Liste, ohne ihn zu beenden. Damit zählt er nicht mehr zur Session, bekommt beim Logout kein SIGHUP mehr und läuft sauber weiter. disown -h %1 lässt den Job in der Liste, schützt ihn aber trotzdem vor SIGHUP. Vollständige Erklärung im Artikel nohup und disown.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Prozesse & Jobs

Zur Übersicht