Sobald ein Terminal-Fenster zugeht, sendet die Shell ein SIGHUP an alle ihre Jobs — und alles, was im Hintergrund lief, stirbt mit. Wer einen langen Build, ein Backup oder einen Server-Prozess startet, braucht einen sauberen Weg, den Prozess vom kontrollierenden Terminal zu entkoppeln. Drei Werkzeuge erledigen das: nohup, disown und setsid. Sie sehen ähnlich aus, arbeiten aber auf unterschiedlichen Ebenen — und nur wer den Unterschied kennt, baut wirklich robuste Hintergrundprozesse.

Das Problem: SIGHUP beim Terminal-Schließen

Wenn du eine Shell startest, erzeugt der Kernel eine Session mit der Shell als Session-Leader und einem kontrollierenden Terminal (tty). Alle Kommandos, die du in dieser Shell startest, werden Teil dieser Session — egal ob im Vordergrund oder im Hintergrund.

Geht das Terminal-Fenster zu (oder bricht die SSH-Verbindung ab), schickt der Kernel ein SIGHUP an den Session-Leader. Die Shell reagiert darauf, indem sie ihrerseits SIGHUP an alle bekannten Jobs weiterreicht. Der Default-Handler von SIGHUP ist „beenden” — und damit reißen alle Hintergrundprozesse mit.

SchrittWas passiert
1.Du startest ./build.sh & — der Job läuft als Kind der Shell
2.Du schließt das Terminal-Fenster
3.Kernel sendet SIGHUP an die Shell (Session-Leader)
4.Bash leitet SIGHUP an alle Jobs aus seiner Tabelle weiter
5.build.sh empfängt SIGHUP, der Default-Handler beendet den Prozess

Drei Werkzeuge unterbrechen diese Kette an unterschiedlichen Stellen: nohup lässt den Prozess SIGHUP von vornherein ignorieren, disown entfernt den Job aus Bash’s Tabelle (Schritt 4 läuft ins Leere), setsid löst den Prozess komplett aus der Session (Schritt 3 erreicht ihn nicht).

nohup — SIGHUP ignorieren

nohup (No Hang-Up) ist das klassische Werkzeug. Es startet ein Programm so, dass das SIGHUP-Signal ignoriert wird — der Prozess hört das Hangup-Signal also gar nicht erst. Zusätzlich kümmert sich nohup um die Standard-Streams: Wenn stdout oder stderr an ein Terminal hängen, leitet es sie automatisch in eine Datei nohup.out (im aktuellen Verzeichnis, oder ersatzweise in ~/nohup.out).

Der klassische Aufruf:

Bash nohup mit Hintergrund-Operator
nohup ./long-task.sh &

Wichtig ist die Reihenfolge: nohup muss vor dem Befehl stehen, weil es ein eigenständiges Programm ist, das den Befehl als Argument startet — nicht ein Shell-Builtin, das nachträglich auf einen laufenden Job wirkt. Das & am Ende schickt den Prozess in den Hintergrund; ohne & läuft nohup zwar SIGHUP-immun, blockiert aber das Terminal.

AspektVerhalten
SIGHUP-Schutzaktiv ab Programmstart (vom Kind geerbt)
Outputnohup.out im CWD, sonst ~/nohup.out
stdinwird auf /dev/null umgelenkt (sonst hinge der Prozess am Terminal)
Voraussetzungmuss vor dem Befehl stehen, vor dem &
Zustand danachProzess hängt weiterhin in der Shell-Session, nur SIGHUP-immun

disown — aus der Job-Tabelle entfernen

disown ist ein Bash-Builtin und arbeitet auf einer ganz anderen Ebene als nohup: Es entfernt einen bereits laufenden Job aus der Job-Tabelle der Shell. Damit weiß die Shell beim Beenden nicht mehr, dass dieser Prozess existiert — und reicht beim Empfang von SIGHUP nichts mehr an ihn weiter.

Die wichtigsten Varianten:

Bash disown — typische Aufrufe
disown %1
disown -h %1
disown -a
disown
AufrufWirkung
disown %1entfernt Job 1 vollständig aus der Job-Tabelle
disown -h %1markiert Job 1 nur als HUP-immun, Job bleibt in jobs sichtbar
disown -awirkt auf alle Jobs der aktuellen Shell
disown (ohne Argument)wirkt auf den aktuellen Job (zuletzt verwendeter %+)

disown ist nur sinnvoll auf bereits laufenden Background-Jobs — also Befehlen, die mit & gestartet oder per Strg + Z und bg in den Hintergrund gelegt wurden. Auf einen Vordergrund-Prozess wirkt es nicht, und vor dem Start eines Befehls geht es ebenfalls nicht. Hat man nohup vergessen, ist disown der nachträgliche Rettungsanker.

setsid — eigene Session starten

setsid geht noch einen Schritt weiter: Es startet den Befehl in einer neuen Session, mit dem neuen Prozess als Session-Leader. Damit ist er kein Mitglied der Shell-Session mehr — und das SIGHUP, das die Shell beim Schließen verteilt, erreicht ihn überhaupt nicht.

Bash setsid für vollständige Detachment
setsid ./long-task.sh > log 2>&1 < /dev/null &

Das ist die Methode, mit der echte Daemons früher von Hand gebaut wurden: fork(), im Kind setsid(), alle Datei-Deskriptoren schließen, neu öffnen auf /dev/null oder eine Logdatei. Heute übernimmt das systemd, aber für ein robustes „Skript einfach detached starten” ist setsid die direkteste Lösung.

AspektVerhalten
Sessionneuer Session-Leader, kein kontrollierendes Terminal
SIGHUP-SchutzSignal wird gar nicht erst zugestellt
Outputnicht automatisch umgelenkt — du musst &gt;, 2&gt;&amp;1, &lt; /dev/null selbst setzen
Voraussetzungmuss vor dem Befehl stehen
Zustand danachProzess gehört nicht mehr zur Shell — jobs zeigt ihn nicht an

Vergleich der vier Werkzeuge

& allein gehört der Vollständigkeit halber dazu — es ist kein Detachment-Mechanismus, nur eine Anweisung an die Shell, nicht zu warten. Der Job bleibt in der Job-Tabelle und stirbt mit ihr.

WerkzeugWann anwendenSIGHUP-SchutzOutput-VerhaltenNeuer Session-LeaderVoraussetzung
&kurz im Hintergrund laufen lassenneinbleibt am Terminalneinnach dem Befehl
nohupklassisches Detachment beim Startja (ignoriert)nohup.out, falls nicht umgeleitetneinvor dem Befehl
disownnachträglich für laufenden Jobja (Job aus Tabelle)unverändertneinJob muss schon laufen
setsidechtes Daemonize, robusteste Varianteja (eigene Session)manuell umlenkenjavor dem Befehl

In der Praxis kombiniert man oft: nohup und & zusammen, oder setsid mit expliziter Umlenkung aller drei FDs. disown ist der nachträgliche Notfallplan.

stdin, stdout und stderr trennen

Selbst SIGHUP-Schutz reicht nicht für ein wirklich detached Programm. Solange der Prozess seine Datei-Deskriptoren 0, 1 und 2 noch ans Terminal hat, hängt er an der TTY. Wird die TTY beim Schließen des Fensters abgebaut, bekommen Schreibversuche auf stdout ein SIGPIPE oder einen EIO-Fehler — und der Prozess stirbt trotzdem.

Die saubere Variante schließt alle drei FDs explizit:

Bash Vollständig detached starten
nohup ./long-task.sh > out.log 2>&1 < /dev/null &
ElementBedeutung
&gt; out.logstdout in Logdatei umlenken (FD 1)
2&gt;&amp;1stderr auf dieselbe Stelle wie stdout (FD 2)
&lt; /dev/nullstdin von /dev/null lesen (FD 0)
&amp;im Hintergrund starten

nohup lenkt automatisch nur stdout um, wenn es ein Terminal ist — stderr und stdin bleiben unangetastet. Wer kein nohup.out will und sicheres Verhalten beim Schließen des Terminals braucht, leitet alle drei explizit um. Bei setsid ist diese Umleitung Pflicht, sonst killt der TTY-Abbau den Prozess trotz neuer Session.

Praxis-Patterns

Die folgenden Idiome decken praktisch alle Fälle ab, in denen man einen Befehl vom Terminal lösen will. Jedes hat seine Stärke.

Klassisch mit nohup:

Bash Klassisches nohup-Pattern
nohup ./long-task.sh > log 2>&1 &

Einfachster, weitverbreiteter Aufruf. SIGHUP wird ignoriert, Output landet in log, stderr im selben Strom. Funktioniert in jeder POSIX-Shell und ist die Standard-Empfehlung in Tutorials.

Nachträglich mit disown:

Bash Job nachträglich freigeben
./long-task.sh > log 2>&1 &
disown

Wenn man nohup vergessen hat oder es nachträglich entscheiden will: Job läuft schon im Hintergrund, disown ohne Argument entfernt den zuletzt gestarteten Job aus der Tabelle. Geht nur in der laufenden Shell, nicht später aus einer anderen Sitzung.

Vollständig detached mit setsid:

Bash Echtes Daemonize
setsid ./long-task.sh > log 2>&1 < /dev/null &

Robusteste Variante: neuer Session-Leader, alle drei FDs umgelenkt. Der Prozess überlebt selbst harte SSH-Disconnects und ist von der ursprünglichen Shell vollständig entkoppelt. jobs zeigt ihn nicht mehr an — verwalten musst du ihn jetzt über die PID.

Mit User-Wechsel:

Bash Detached unter anderem User
sudo -u www-data nohup ./serve.sh > /var/log/serve.log 2>&1 &

Klassisches Pattern, wenn ein Service unter einem Service-User laufen soll, aber kein systemd-Unit existiert. sudo -u wechselt den Effective User, nohup schützt vor SIGHUP. Für Produktion bleibt ein systemd-Service trotzdem die saubere Lösung.

Stop-Wait-Idiom:

Bash Hintergrund mit nachgelagertem Warten
nohup ./build.sh > log 2>&1 &
wait

Praktisch für Skripte: Mehrere Tasks parallel starten, dann mit wait auf alle warten. Der nohup-Anteil ist dabei nicht zwingend, sorgt aber dafür, dass die Tasks auch dann sauber weiterlaufen, wenn das umgebende Skript zwischendurch SIGHUP bekommt.

zsh-Spezialität &!:

Bash zsh-Kürzel: starten und sofort disownen
./long-task.sh > log 2>&1 &!

Nur in zsh: Der Operator &! startet im Hintergrund und ruft disown in einem Rutsch. Bash kennt das nicht — dort braucht es zwei separate Befehle.

Häufige Fallstricke

nohup muss VOR dem Befehl stehen

nohup ist ein eigenständiges Programm, das den eigentlichen Befehl als Argument startet. Konstrukte wie cmd | nohup ... oder cmd; nohup haben keinerlei Schutzwirkung auf cmd. Faustregel: nohup kommt direkt vor dem Befehl, das & ganz ans Ende der Zeile.

disown ohne Argument trifft den aktuellen Job

Ohne Job-Spec wirkt disown auf den zuletzt gestarteten oder per fg/bg referenzierten Job (%+). In Skripten ist das gefährlich — wenn zwischen Job-Start und disown noch andere Job-Operationen stattfinden, kann der falsche Job betroffen sein. Sicherer ist disown $!, was explizit den Hintergrund-Job des letzten & adressiert.

nohup.out kann unkontrolliert wachsen

Wenn man nohup ohne explizite Umlenkung benutzt, sammelt sich aller stdout-Output in nohup.out (oder ~/nohup.out). Bei lange laufenden, geschwätzigen Programmen wird die Datei schnell mehrere Gigabyte groß und füllt die Partition. Saubere Praxis: immer explizit &gt; logfile 2&gt;&amp;1 setzen, niemals auf das Default-Verhalten verlassen.

nohup leitet nur stdout um, nicht stderr

Das automatische Umlenken nach nohup.out betrifft nur stdout — stderr bleibt am Terminal hängen, sofern es nicht eigenständig umgelenkt wird. Bricht das Terminal weg, schreibt der Prozess auf einen ungültigen FD und kann durch SIGPIPE oder EIO trotzdem sterben. Immer 2&gt;&amp;1 mitschreiben.

setsid braucht alle drei FDs zumachen

Eine neue Session reicht nicht, wenn die Datei-Deskriptoren 0, 1, 2 noch am alten Terminal hängen. Beim TTY-Abbau gibt es Schreibfehler — und der Prozess stirbt trotz eigener Session. Saubere setsid-Aufrufe haben immer &gt; ... 2&gt;&amp;1 &lt; /dev/null. Sonst bringt setsid keinen Vorteil gegenüber nohup.

disown -h hält den Job in der Job-Liste

Mit dem Flag -h markiert disown den Job nur als HUP-immun, lässt ihn aber in jobs sichtbar — die Shell wartet beim Exit ggf. weiter darauf. Ohne -h verschwindet der Job vollständig aus der Tabelle und gilt aus Shell-Sicht als nicht existent. Welche Variante richtig ist, hängt davon ab, ob die Shell den Job noch verwalten soll.

Cron- vs. Service-Idiom

nohup, disown und setsid sind Werkzeuge für interaktive Sessions oder kurze Skript-Detachments. Für regelmäßig wiederkehrende Tasks ist Cron das passende Werkzeug — Cron-Jobs laufen ohnehin ohne kontrollierendes Terminal. Für dauerhaft laufende Dienste (Webserver, Worker, Daemons) ist ein systemd-Service die saubere Lösung: Restart bei Crash, strukturierte Logs via journald, cgroup-Limits, definierte Abhängigkeiten. Die manuelle setsid-Variante ist eher Notnagel.

systemd-Service ist die saubere Daemon-Lösung

Wer einen langlebigen Prozess unter Linux betreibt, sollte ihn als systemd-Unit registrieren statt mit nohup oder setsid zu basteln. systemd übernimmt PID-Tracking, Restart-Policy, Output-Routing nach journald, cgroup-basierte Ressourcenlimits und sauberen Shutdown bei Reboot. Die nohup-Variante ist gut für Ad-hoc-Tasks und einmalige Builds — nicht für produktive Services. Details im systemd-Kapitel.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Prozesse & Jobs

Zur Übersicht