jobs — Shell-Jobs starten, anhalten und in den Hintergrund schicken

Job-Control der Shell mit jobs, fg, bg, &, Ctrl+Z und disown: Prozesse in einer interaktiven Shell starten, anhalten, fortsetzen und ablösen.

Sobald ein Kommando länger läuft, willst du dein Terminal nicht blockieren – genau dafür gibt es die Job-Control der Shell. Mit &, Ctrl+Z, jobs, fg, bg und disown startest du Prozesse im Hintergrund, hältst sie an, holst sie zurück oder löst sie ganz vom Terminal. Dieser Guide zeigt dir die Builtins und Job-Spezifizierer, mit denen du mehrere Aufgaben gleichzeitig im Griff behältst – vom schnellen sleep 300 & bis zur begrenzten parallelen Warteschlange.

Jobs starten

<command> & — Führt ein Kommando im Hintergrund aus. Die Shell gibt „[n] PID" aus und kehrt sofort zurück.

sleep 300 &

<command1> & <command2> & <command3> & — Startet mehrere Hintergrundjobs in einer Zeile.

make build & make docs & make test &

( <command> & ) — Führt ein Kommando in einer Subshell aus, sodass es den Elternprozess überlebt und nicht in „jobs" auftaucht.

( long-running-task & )

<command> &! — Zsh: startet im Hintergrund UND löst sofort ab (disown) — überlebt das Beenden der Shell, kein SIGHUP.

long-running-task &!

<command> |& — Schickt eine Pipeline samt stderr in den Hintergrund (bash 4+, zsh).

make 2>&1 | tee build.log &

Jobs anhalten

Ctrl+Z — Sendet SIGTSTP an den Vordergrundprozess — hält ihn an und gibt die Kontrolle an die Shell zurück.

vim file.txt   # mit Ctrl+Z anhalten, mit fg zurückholen

Ctrl+Y — Sendet SIGTSTP erst, wenn der Prozess Eingaben lesen will (verzögertes Anhalten, nur BSD/macOS).

less bigfile   # Ctrl+Y hält beim nächsten Lesezugriff an

kill -STOP <pid> — Hält einen beliebigen Prozess per PID an (nicht nur den im Vordergrund).

kill -STOP 4242

kill -CONT <pid> — Setzt einen angehaltenen Prozess per PID fort — das Gegenstück zu -STOP.

kill -CONT 4242

Jobs auflisten

jobs — Listet alle Jobs der aktuellen Shell mit Nummer, Status und Kommando auf.

$ jobs
[1]+  Running                 sleep 300 &
[2]-  Stopped                 vim file.txt

jobs -l — Listet Jobs inklusive ihrer PID auf.

jobs -l

jobs -p — Gibt nur die PIDs der Jobs aus (eine pro Zeile) — praktisch fürs Skripting.

jobs -p | xargs kill

jobs -r — Listet nur laufende Jobs auf.

jobs -r

jobs -s — Listet nur angehaltene Jobs auf.

jobs -s

jobs -n — Listet nur Jobs auf, deren Status sich seit der letzten Benachrichtigung geändert hat.

jobs -n

jobs %<n> — Zeigt den Status eines bestimmten Jobs.

jobs %1

Job-Spezifizierer

%<n> — Bezieht sich auf Jobnummer n (die von „jobs" angezeigte Nummer).

fg %2

%% or %+ — Der aktuelle Job (zuletzt angehalten oder in den Hintergrund geschickt). Implizites Ziel von „fg"/„bg" ohne Argumente.

fg %%

%- — Der vorige Job (der vor %+).

fg %-

%<string> — Job, dessen Kommando mit der angegebenen Zeichenkette beginnt.

fg %vim

%?<string> — Job, dessen Kommando die angegebene Zeichenkette irgendwo enthält.

kill %?make

Vordergrund & Hintergrund

fg — Holt den aktuellen (zuletzt verwendeten) Job in den Vordergrund.

fg

fg %<n> — Holt Jobnummer n in den Vordergrund.

fg %1

bg — Setzt den aktuell angehaltenen Job im Hintergrund fort (läuft weiter, aber ohne Terminal-Eingabe).

Ctrl+Z, dann „bg", um losgelöst weiterzulaufen

bg %<n> — Setzt einen bestimmten angehaltenen Job im Hintergrund fort.

bg %2

%<n> — Ein nackter Job-Spezifizierer holt den Job in den Vordergrund (Kurzform für „fg %n").

%1

%<n> & — Ein nackter Job-Spezifizierer mit „&" setzt ihn im Hintergrund fort (Kurzform für „bg %n").

%1 &

Jobs beenden & Signale senden

kill %<n> — Sendet SIGTERM an einen Job per Jobnummer.

kill %1

kill -9 %<n> — Erzwingt das Beenden (SIGKILL) eines Jobs, der sich nicht beenden lässt.

kill -9 %2

kill -<signal> %<n> — Sendet ein beliebiges Signal per Name oder Nummer an einen Job.

kill -HUP %1

kill %<string> — Beendet den Job, dessen Kommando mit beginnt.

kill %make

kill $(jobs -p) — Sendet SIGTERM an alle aktuellen Jobs der Shell.

kill $(jobs -p)

Jobs ablösen (disown)

disown — Entfernt den jüngsten Job aus der Job-Tabelle der Shell — er läuft weiter, wird aber nicht mehr verfolgt.

long-task & disown

disown %<n> — Löst einen bestimmten Job per Nummer ab.

disown %2

disown -h %<n> — Behält den Job in der Tabelle, markiert ihn aber so, dass er beim Beenden der Shell KEIN SIGHUP erhält.

disown -h %1

disown -a — Löst alle Jobs von der Shell ab.

disown -a

disown -r — Löst nur laufende Jobs ab (lässt angehaltene in der Tabelle).

disown -r

shopt -s huponexit — Bash: sendet beim Beenden der Shell SIGHUP an alle Jobs (Standard ist AUS — sie überleben).

shopt -s huponexit

setopt nohup — Zsh: sendet beim Beenden der Shell KEIN SIGHUP an die Jobs.

setopt nohup

Auf Jobs warten

wait — Blockiert, bis alle Hintergrundjobs der aktuellen Shell beendet sind.

task1 & task2 & task3 & wait

wait %<n> — Wartet auf einen bestimmten Job — der Exit-Status von wait entspricht dem des Jobs.

long-task & wait %1; echo "exited $?"

wait <pid> — Wartet auf eine bestimmte PID (ab bash 5.1+ auch auf Hintergrundjobs außerhalb der aktuellen Shell).

wait 4242

wait -n — Wartet auf IRGENDEINEN einzelnen Hintergrundjob (bash 4.3+, zsh). Nützlich für parallele Warteschlangen.

for i in 1 2 3; do task $i & done; wait -n

wait -f <pid> — Wartet, bis der Prozess tatsächlich endet, selbst wenn sein Elternprozess ihn bereits eingesammelt hat (bash 5.1+).

wait -f 4242

Muster & Fallstricke

command > out.log 2>&1 & — Schickt ein Kommando in den Hintergrund und leitet stdout und stderr in eine Datei (sonst landet streunende Ausgabe im Terminal).

make build > build.log 2>&1 &

command < /dev/null > out.log 2>&1 & — Löst vollständig von Terminal-stdin/-stdout — kein SIGTTIN/SIGTTOU, wenn das Terminal geschlossen wird.

long-task < /dev/null > out.log 2>&1 &

set -m / set +m — Schaltet die Job-Control ein oder aus. In Skripten standardmäßig aus — mit „set -m" einschalten, um %n im Skript zu nutzen.

set -m; long-task & fg %1

set -b — Bash: meldet Statusänderungen von Jobs SOFORT statt erst vor dem nächsten Prompt.

set -b

$! — PID des zuletzt in den Hintergrund geschickten Prozesses — kombiniere sie mit „wait" oder „kill", um einen bestimmten Job zu verfolgen.

long-task & echo $! > task.pid

trap 'kill $(jobs -p) 2>/dev/null' EXIT — Aufräumen: beendet alle Kind-Jobs, wenn die Shell oder das Skript endet.

trap 'kill $(jobs -p) 2>/dev/null' EXIT

Praxisrezepte

Ctrl+Z, bg, disown — Befördert ein Vordergrundkommando zu einem vollständig losgelösten Hintergrundprozess — überlebt den Logout.

tail -f big.log   # Ctrl+Z
bg
disown

for f in *.mp4; do ffmpeg ... "$f" & done; wait — Verarbeitet einen Stapel parallel und wartet, bis alles fertig ist.

for f in *.mp4; do ffmpeg -i "$f" "${f%.mp4}.webm" & done; wait

Parallele Warteschlange mit -n (max. parallel) — Verarbeitet Arbeitsaufträge mit einer begrenzten Anzahl paralleler Jobs.

max=4; for i in {1..20}; do (( $(jobs -r | wc -l) >= max )) && wait -n; task $i & done; wait

kill %1 && wait %1 2>/dev/null — Beendet einen Job und wartet, bis die Shell ihn vollständig eingesammelt hat (unterdrückt die „Terminated"-Meldung).

kill %1 && wait %1 2>/dev/null

Fazit

Die Job-Control macht aus einer einzelnen Shell einen kleinen Prozess-Manager: jobs verschafft dir den Überblick, Ctrl+Z plus bg befördert ein hängendes Kommando in den Hintergrund, und fg holt es wieder zurück. Wichtig zu wissen: Hintergrundjobs hängen am Terminal. Beendest du die Shell oder loggst dich aus, erhalten sie standardmäßig ein SIGHUP und sterben – mitsamt noch nicht gespeicherter Arbeit. Soll ein Job das Logout überleben, löse ihn mit disown -h ab oder starte ihn gleich unter nohup, screen oder tmux. Und denk daran: Diese Builtins wirken nur in einer interaktiven Shell; in Skripten musst du die Job-Control erst mit set -m aktivieren.

Verwandte Kommandos

  • bash – die Bourne-Again-Shell, in der die Job-Control-Builtins leben
  • kill – Signale an Prozesse und Jobs senden (SIGTERM, SIGKILL, SIGCONT)
  • nohup – Prozesse gegen SIGHUP immunisieren, damit sie den Logout überleben