Unterschied zwischen nohup, disown und &

577

Was sind die Unterschiede zwischen

$ nohup foo

und

$ foo &

und

$ foo & 
$ disown
Lesmana
quelle
50
Warten Sie, können Sie ohne Angabe einer PID verweigern? Toll!
Ripper234
34
Es gibt auch foo &!Dinge, die gleichbedeutend sein sollten, wenn man sie von Anfang an ablehnt.
user4514 18.11.12
26
Bash unterstützt &! Nicht.
Jonas Kongslund
20
foo & disownsofort ablehnen.
Strg-Alt-Delor
9
Ich würde gerne eine Erwähnung sehen setsid, und wie es sich auf disownund beziehtnohup
YoungFrog

Antworten:

557

Schauen wir uns zunächst an, was passiert, wenn ein Programm von einer interaktiven Shell (die mit einem Terminal verbunden ist) ohne &(und ohne Umleitung) gestartet wird . Nehmen wir also an, Sie haben gerade Folgendes eingegeben foo:

  • Der laufende Prozess foowird erstellt.
  • Der Prozess erbt stdin, stdout und stderr von der Shell. Daher wird es auch an dasselbe Terminal angeschlossen.
  • Wenn die Shell ein empfängt SIGHUP, sendet sie auch ein SIGHUPan den Prozess (wodurch der Prozess normalerweise beendet wird).
  • Andernfalls wartet die Shell (wird blockiert), bis der Prozess beendet ist.

Schauen wir uns nun an, was passiert, wenn Sie den Prozess in den Hintergrund stellen, also Folgendes eingeben foo &:

  • Der laufende Prozess foowird erstellt.
  • Der Prozess erbt stdout / stderr von der Shell (sodass weiterhin auf das Terminal geschrieben wird).
  • Der Prozess erbt im Prinzip auch stdin, aber sobald er versucht, von stdin zu lesen, wird er angehalten.
  • Es wird in die Liste der von der Shell verwalteten Hintergrundjobs aufgenommen, was insbesondere Folgendes bedeutet:
    • Es wird mit aufgelistet jobsund kann über %n(wo nist die Auftragsnummer) abgerufen werden .
    • Es kann mit in einen Vordergrundjob verwandelt werden fg. In diesem Fall wird es so fortgesetzt, als hätten Sie es nicht verwendet &(und wenn es aufgrund des Versuchs, von der Standardeingabe zu lesen, angehalten wurde, kann es jetzt mit dem Lesen vom Terminal fortfahren).
    • Wenn die Shell ein empfangen hat SIGHUP, sendet sie auch ein SIGHUPan den Prozess. Abhängig von der Shell und möglicherweise von den für die Shell festgelegten Optionen wird beim Beenden der Shell auch ein SIGHUPan den Prozess gesendet.

Nun disownentfernt den Auftrag aus der Auftragsliste der Schale, so dass alle Unterpunkte gelten nicht mehr (einschließlich dem Prozess eines gesendet SIGHUPvon der Shell). Beachten Sie jedoch, dass es immer noch mit dem Terminal verbunden ist. Wenn also das Terminal zerstört wird (was passieren kann, wenn es sich um ein Pty handelt, wie das, das von xtermoder erstellt wurde ssh, und das Steuerungsprogramm beendet wird, indem Sie das xterm schließen oder die SSH- Verbindung beenden ). schlägt das Programm fehl, sobald versucht wird, von der Standardeingabe zu lesen oder auf die Standardausgabe zu schreiben.

Was den nohupFall ist, auf der anderen Seite, ist effektiv aus dem Terminal , den Prozess zu trennen:

  • Es schließt die Standardeingabe (das Programm wird nicht fähig sein , auch jede Eingabe zu lesen, wenn es im Vordergrund ausgeführt wird. Nicht angehalten wird, sondern einen Fehlercode oder empfangen EOF).
  • Standardausgabe und Standardfehler werden in die Datei umgeleitet nohup.out, sodass das Programm beim Fehlschlagen des Terminals nicht fehlschlägt, um in die Standardausgabe zu schreiben.
  • Es verhindert, dass der Prozess ein SIGHUP(also den Namen) empfängt .

Beachten Sie, dass nohupsie nicht den Prozess von der Shell-Auftragssteuerung entfernen und auch nicht setzt sie nicht im Hintergrund (aber da ein Vordergrund nohupJob mehr oder weniger nutzlos ist, würden Sie es in der Regel setzen in den Hintergrund verwenden &). Anders als bei disownwird Ihnen die Shell beispielsweise weiterhin mitteilen, wann der Nohup-Job abgeschlossen ist (es sei denn, die Shell wird zuvor beendet).

Um es zusammenzufassen:

  • & Setzt den Job in den Hintergrund, dh, der Versuch, Eingaben zu lesen, wird blockiert, und die Shell wartet nicht auf ihren Abschluss.
  • disownEntfernt den Prozess aus der Jobsteuerung der Shell, lässt ihn jedoch weiterhin mit dem Terminal verbunden. Eines der Ergebnisse ist, dass die Shell es nicht sendet SIGHUP. Offensichtlich kann es nur auf Hintergrundjobs angewendet werden, da Sie es nicht eingeben können, wenn ein Vordergrundjob ausgeführt wird.
  • nohupTrennt den Prozess vom Terminal, leitet seinen Ausgang an um nohup.outund schirmt ihn ab SIGHUP. Einer der Effekte (der benennende) ist, dass der Prozess keine gesendeten Nachrichten empfängt SIGHUP. Es ist völlig unabhängig von der Jobkontrolle und kann grundsätzlich auch für Vordergrundjobs verwendet werden (obwohl dies nicht sehr nützlich ist).
Celtschk
quelle
8
+1 Danke. Was passiert dann, wenn disown, nohup und & zusammen verwendet werden?
Tim
15
Wenn Sie alle drei gemeinsam verwenden, wird der Prozess im Hintergrund ausgeführt, aus der Jobsteuerung der Shell entfernt und effektiv vom Terminal getrennt.
Celtschk
1
Was ist der Unterschied zwischen disown %1und disown -h %1? Die zweite Aufgabe wird als regulärer Job ausgeführt (ignoriert jedoch das HUP-Signal), bis das Terminal beendet wird.
Schemata
4
Vielleicht wert einschließlich (foo&)Unterschale
Jiggunjer
168

Bei Verwendung von &wird das Programm im Hintergrund ausgeführt, sodass Sie eine neue Shell-Eingabeaufforderung erhalten, anstatt zu blockieren, bis das Programm endet. nohupund disownsind weitgehend unabhängig; Sie unterdrücken SIGHUP-Signale (Auflegen), damit das Programm nicht automatisch beendet wird, wenn das steuernde Terminal geschlossen wird. nohuptut dies, wenn der Job zum ersten Mal beginnt. Wenn Sie zu nohupBeginn keinen Job haben, können Sie disowneinen laufenden Job ändern. Ohne Argumente wird der aktuelle Job geändert, der gerade im Hintergrund ausgeführt wurde

Michael Mrozek
quelle
10
Kleiner Unterschied zwischen "nohup" und "disown": Der Befehl "disown" entfernt ihn aus Ihrer Auftragsliste. Nohup wird nicht.
Shawn J. Goff
191
nohupund von disownbeiden kann gesagt werden SIGHUP, dass sie auf unterschiedliche Weise unterdrücken . nohupveranlasst das Programm, das Signal zunächst zu ignorieren (das Programm kann dies ändern). nohupversucht auch, dafür zu sorgen, dass das Programm kein steuerndes Terminal hat, damit es nicht SIGHUPvom Kernel gesendet wird, wenn das Terminal geschlossen wird. disownist rein innerlich in der Schale; es bewirkt, dass die Shell nicht sendet, SIGHUPwenn sie beendet wird.
Gilles
27
@ Gilles, dein Kommentar ist eine Antwort wert.
Lesmana
5
Nur eine Klarstellung zu @ ShawnJ.Goffs Kommentar zum disownEntfernen des Jobs von der Jobliste . Wenn Sie keine Option angeben, wird diese aus der Auftragsliste entfernt. Allerdings , wenn Sie die angeben -hOption, jede jobspec wird nicht aus der Tabelle entfernt. Stattdessen wird es so erstellt, dass SIGHUPes nicht an den Job gesendet wird, wenn die Shell ein empfängt SIGHUP.
Dienstag,
4
Nur um zu verdeutlichen, &gibt Ihnen using kein Terminal, es löst sich stdinvom Prozess und veranlasst, dass es im Hintergrund ausgeführt wird, aber beides stdoutund stderrist immer noch mit dem aktuellen tty verbunden. Dies bedeutet, dass Sie möglicherweise Text aus verschiedenen Programmen gemischt bekommen, was ziemlich ärgerlich sein kann, wenn Sie dies tun gimp &und viele GTK + -Fehler erhalten, während Sie versuchen, dieses tty für etwas anderes zu verwenden.
Frank
8

Hier ist meine Erfahrung mit dem Versuch, Soffice im Hintergrund auszuführen, und zwar nach einem nicht beendenden Befehl (z tail. B. ). Für dieses Beispiel werde ich verwenden sleep 100.

&

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Ich sehe Office- Protokolle / durch Drücken von Ctrl- COffice-Stopps

nohup .. &

#!/bin/bash
nohup /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Ich sehe keine Office- Protokolle / durch Drücken von Ctrl- COffice-Stopps

& verleugnen

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard & disown
sleep 100

Ich sehe Office- Protokolle / durch Drücken von Ctrl- COffice-Stopps

setsid .. &

#!/bin/bash
setsid /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Ich sehe Office- Protokolle / durch Drücken von Ctrl- COffice STOPPT NICHT

Um Speicherplatz zu sparen
nohup setsid ..:: zeigt keine Protokolle / Soffices an STOPPT NICHT an Ctrl-C
nohup mit & disownam Ende: zeigt keine Protokolle / Soffices an Ctrl-C

Marinos An
quelle
2
Obwohl ich die Mühe schätze, setsid zu erwähnen und zu zeigen, was in dieser speziellen Situation passiert, würde ich mir eine gründlichere Antwort wünschen. Insbesondere die Unterschiede und Ähnlichkeiten jeder Lösung, sowohl sichtbar (was passiert, wenn die Shell oder das Terminal geschlossen wird, wohin die Ausgabe geht, ...) als auch unsichtbar (wie Dinge unter der Haube geschehen und ihre Auswirkungen). Die akzeptierte Antwort ist dafür eine gute Basis.
YoungFrog
1
@YoungFrog Dem werde ich zustimmen!
Marinos An
Bei mir nohup ⟨command⟩ & disownhört der erstellte Prozess nicht auf Ctrl+C.
k.stm
@ k.stm Hast du es versucht soffice? sofficeBefehl scheint etwas anderes zu haben. Deshalb habe ich überlegt, es hier in der Regel als Ausnahme hinzuzufügen. Wenn Sie z. B.: verwenden nohup .. &, wird Ctrl-cder Befehl durch Drücken von normalerweise nicht angehalten, jedoch durch Drücken von soffice. Ich warte, bis jemand darauf tritt und erkläre, warum dies bei soffice passiert :)
Marinos An
@MarinosAn Ja, ich habe es getan. Ich rannte nohup soffice &und drückte Ctrl+C. Nichts ist passiert, wie erwartet.
k.stm