Was ist der Unterschied zwischen dem Ausführen eines Programms als Daemon und dem Verwerfen des Programms in den Hintergrund mit '&'?

45

Was sind die praktischen Unterschiede aus sysadmin-Sicht beim Bereitstellen von Diensten auf einem Unix-basierten System?

user1561108
quelle

Antworten:

31

Die traditionelle Art der Dämonisierung ist:

fork()
setsid()
close(0) /* and /dev/null as fd 0, 1 and 2 */
close(1)
close(2)
fork()

Dies stellt sicher, dass sich der Prozess nicht mehr in derselben Prozessgruppe wie das Terminal befindet und somit nicht zusammen mit ihm beendet wird. Die E / A-Umleitung bewirkt, dass die Ausgabe nicht auf dem Terminal angezeigt wird.

Dennis Kaarsemaker
quelle
5
Wenn also ein Terminal, das einen Hintergrundprozess (&) erzeugt, geschlossen wird, wird der Hintergrundprozess ebenfalls beendet.
user1561108
9
Der Prozess erhält SIGHUP, wenn das Terminal beendet wird. Der Standard-Handler für dieses Signal ist das Beenden des Prozesses.
Dennis Kaarsemaker
12
Bitte fügen Sie die &Teilerklärung Ihrer Antwort hinzu. Es scheint unvollständig zu sein, wenn Sie die ursprüngliche Frage überprüfen.
MTK
1
Das liegt daran, dass das Ausführen von Dingen im Hintergrund mit & nichts Besonderes
bewirkt
33

Für einen Daemon ist das, was Sie wollen, ein Prozess, der an nichts gebunden ist. Zumindest möchten Sie, dass es sich in einer eigenen Sitzung befindet, nicht an ein Terminal angehängt wird, keine von dem übergeordneten Element geerbten Dateideskriptoren für irgendetwas geöffnet sind und kein übergeordnetes Element (außer init) über den aktuellen Status verfügt Verzeichnis in /, um ein umount nicht zu verhindern ...

Um sich von einem Terminal zu trennen, erstellen Sie eine neue Sitzung. Um jedoch eine Sitzung zu erstellen, dürfen Sie kein Gruppen- (oder Sitzungs-) Leiter sein. Daher ist es am besten, einen neuen Prozess zu starten. Unter der Annahme, dass das übergeordnete Element beendet wird, bedeutet dies auch, dass der Prozess kein übergeordnetes Element mehr hat und von init übernommen wird. Schließen Sie dann alle möglichen Dateideskriptoren (Sie chdir("/")können das aktuelle Arbeitsverzeichnis nicht schließen , um diese Ressource wie bei Dateideskriptoren freizugeben, sodass /das Aufheben der Bereitstellung von Verzeichnissen durch die aktuellen Arbeitsverzeichnisse zumindest nicht verhindert wird).

Da dieser Prozess ein Sitzungsleiter ist, besteht die Gefahr, dass er, falls er jemals ein Endgerät öffnet, zum Steuerungsprozess dieses Endgeräts wird. Durch ein zweites Gabeln wird sichergestellt, dass dies nicht passiert.

Auf der anderen Seite gibt & in interaktiven Shells einen Prozess aus und erstellt eine neue Prozessgruppe (um nicht in der Vordergrund-Prozessgruppe des Terminals zu sein), und in nicht interaktiven Shells gibt es einen Prozess aus und ignoriert SIGINT darin. Es löst sich nicht vom Terminal, schließt keine Dateideskriptoren (obwohl einige Shells stdin wieder öffnen /dev/null) ...

Stéphane Chazelas
quelle
Was nützt chdir ("/")? kann ich den Dateideskriptor schließen?
Timothy Leung
@ TimothyLeung, siehe bearbeiten.
Stéphane Chazelas
8

Der Unterschied zwischen dem Ausführen eines Programms / Prozesses als Daemon und dem Verzweigen in den Hintergrund mithilfe des kaufmännischen Und-Zeichens hängt im Wesentlichen mit dem Eigentumsverhältnis zusammen.

In den meisten Fällen ist der übergeordnete Prozess eines Dämons der Init- Prozess (der allererste Prozess, der auf einem Unix-System gestartet wird). Da der Dämon diesem Prozess untergeordnet ist, haben Sie als nicht privilegierter Benutzer keine direkte Kontrolle darüber . Wenn Sie hingegen ein Programm / einen Prozess in den Hintergrund verschieben, können Sie es jederzeit wieder in den Vordergrund rufen und / oder beenden.

Odaym
quelle
1
Um auch die oben genannte technische Seite des Lösens eines Prozesses zu beantworten,
anstatt
7

Mit command &Ihr Prozess wird durch ein SIGHUP-Signal beendet, wenn der Elternteil stirbt.

Sysadmins haben jedoch Zugriff auf einige Problemumgehungen.

Auf einem Bash-System können Sie Folgendes verwenden:

(trap '' HUP; command) &

Dies öffnet eine Subshell, fängt das HUPSignal mit einem leeren Handler ein und / gabelt es.

Die Ausgabe wird möglicherweise weiterhin an die falsche Adresse umgeleitet tty. Oder verloren gehen.
Sie beheben können , dass mit &>command.out, 1>output.outoder2>errors.out

Auf den meisten Systemen haben Sie möglicherweise auch Zugriff auf den nohupBefehl.
nohupvereinfacht diesen Vorgang erheblich. Es ist ziemlich normal, aber ich habe festgestellt, dass es in vielen eingebetteten ARM-Distributionen von busybox fehlt. Du schreibst einfach:

nohup command &

..und du bist fertig. Die Ausgabe wird umgeleitet, IIRC nach nohup.out, aber dieser Dateiname kann mit einer Option geändert werden.

ZJR
quelle
2
Zu beachten ist, dass man mit ZSH command &später eine von der Shell entkoppeln kann, mit disownder dann als Post-Nohup gearbeitet wird.
Mathe