# 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.

Source: https://www.jpkc.com/db/cheatsheets/shell-system/jobs/

<!-- PROSE:intro -->
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.
<!-- PROSE:intro:end -->

## Jobs starten

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

```bash
sleep 300 &
```

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

```bash
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.

```bash
( long-running-task & )
```

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

```bash
long-running-task &!
```

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

```bash
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.

```bash
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).

```bash
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).

```bash
kill -STOP 4242
```

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

```bash
kill -CONT 4242
```

## Jobs auflisten

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

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

`jobs -l` — Listet Jobs inklusive ihrer PID auf.

```bash
jobs -l
```

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

```bash
jobs -p | xargs kill
```

`jobs -r` — Listet nur laufende Jobs auf.

```bash
jobs -r
```

`jobs -s` — Listet nur angehaltene Jobs auf.

```bash
jobs -s
```

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

```bash
jobs -n
```

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

```bash
jobs %1
```

## Job-Spezifizierer

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

```bash
fg %2
```

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

```bash
fg %%
```

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

```bash
fg %-
```

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

```bash
fg %vim
```

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

```bash
kill %?make
```

## Vordergrund & Hintergrund

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

```bash
fg
```

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

```bash
fg %1
```

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

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

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

```bash
bg %2
```

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

```bash
%1
```

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

```bash
%1 &
```

## Jobs beenden & Signale senden

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

```bash
kill %1
```

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

```bash
kill -9 %2
```

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

```bash
kill -HUP %1
```

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

```bash
kill %make
```

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

```bash
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.

```bash
long-task & disown
```

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

```bash
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.

```bash
disown -h %1
```

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

```bash
disown -a
```

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

```bash
disown -r
```

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

```bash
shopt -s huponexit
```

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

```bash
setopt nohup
```

## Auf Jobs warten

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

```bash
task1 & task2 & task3 & wait
```

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

```bash
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).

```bash
wait 4242
```

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

```bash
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+).

```bash
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).

```bash
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.

```bash
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.

```bash
set -m; long-task & fg %1
```

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

```bash
set -b
```

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

```bash
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.

```bash
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.

```bash
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.

```bash
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.

```bash
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).

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

<!-- PROSE:outro -->
## 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.

## Weiterführende Links

- [GNU Bash: Job Control](https://www.gnu.org/software/bash/manual/html_node/Job-Control.html) – die offizielle Bash-Referenz zu Vorder- und Hintergrundjobs sowie Signalen (englisch)
- [Wikipedia: Hintergrundprozess](https://de.wikipedia.org/wiki/Hintergrundprozess) – Erklärung von Vorder- und Hintergrundprozessen unter Unix
<!-- PROSE:outro:end -->

## Verwandte Kommandos

- [bash](https://www.jpkc.com/db/cheatsheets/shell-system/bash/) – die Bourne-Again-Shell, in der die Job-Control-Builtins leben
- [kill](https://www.jpkc.com/db/cheatsheets/shell-system/kill/) – Signale an Prozesse und Jobs senden (SIGTERM, SIGKILL, SIGCONT)
- [nohup](https://www.jpkc.com/db/cheatsheets/shell-system/nohup/) – Prozesse gegen SIGHUP immunisieren, damit sie den Logout überleben

