GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Erhalten Hintergrundprozesse beim Abmelden ein SIGHUP?

Lösung 1:

Antwort gefunden.

Für BASH hängt dies vom huponexit ab Shell-Option, die mit dem eingebauten shopt angezeigt und/oder eingestellt werden kann Befehl.

Sieht so aus, als ob diese Option standardmäßig deaktiviert ist, zumindest auf RedHat-basierten Systemen.

Weitere Informationen auf der BASH-Manpage:

Die Shell wird standardmäßig beim Empfang eines SIGHUP beendet. Vor dem Beenden sendet eine interaktive Shell das SIGHUP erneut an alle laufenden oder angehaltenen Jobs. Gestoppte Jobs erhalten SIGCONT, um sicherzustellen, dass sie das SIGHUP erhalten. Um zu verhindern, dass die Shell das Signal an einen bestimmten Job sendet, sollte er mit dem eingebauten Disown aus der Jobs-Tabelle entfernt werden (siehe SHELL BUILTIN COMMANDS unten) oder mit disown -h so markiert werden, dass er kein SIGHUP empfängt.

Wenn die Shell-Option huponexit mit shopt gesetzt wurde, sendet bash ein SIGHUP an alle Jobs, wenn eine interaktive Login-Shell beendet wird.

Lösung 2:

Es wird in meinen Tests SIGHUP gesendet:

Schale1:

[[email protected]: ~] ssh localhost
[[email protected]: ~] perl -e sleep & 
[1] 1121
[[email protected]: ~] ps
  PID TTY          TIME CMD
 1034 pts/46   00:00:00 zsh
 1121 pts/46   00:00:00 perl
 1123 pts/46   00:00:00 ps

Shell2:

strace -e trace=signal -p1121

Wieder Shell1:

[[email protected]: ~] exit
zsh: you have running jobs.
[[email protected]: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.

Wieder Shell2 :

strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached

Warum läuft es noch?:
Advanced Programming in the Unix Environment von Stevens behandelt dies in Abschnitt 9.10:Verwaiste Prozessgruppen. Der relevanteste Abschnitt ist:

Da die Prozessgruppe verwaist ist, wenn der Elternteil endet, verlangt POSIX.1, dass jedem Prozess in der neu verwaisten Prozessgruppe, der gestoppt wird (wie unser Kind), das Auflegesignal (SIGHUP) gefolgt vom Fortsetzungssignal (SIGCONT) gesendet wird.

Dies bewirkt, dass das Kind nach der Verarbeitung des Auflegesignals fortgesetzt wird. Die Standardaktion für das Auflegesignal besteht darin, den Prozess zu beenden, sodass wir einen Signalhandler bereitstellen müssen, um das Signal abzufangen. Wir erwarten daher, dass printf in der Funktion sig_hup vor printf in der Funktion pr_ids erscheint.

Lösung 3:

Ich habe einige Tests mit CentOS 7.1 und Bash durchgeführt. Beachten Sie, dass dies huponexit bedeutet ist off standardmäßig und war für die meisten meiner Tests ausgeschaltet.

Sie benötigen nohup wenn Sie einen Job in einem Terminal starten, denn wenn Sie dieses Terminal schließen, ohne die Shell sauber zu verlassen , das Terminal sendet bash das SIGHUP-Signal an die Shell, die es dann an alle untergeordneten Elemente sendet. Wenn Sie die Shell sauber verlassen, muss der Job bereits im Hintergrund laufen, damit Sie exit eingeben können oder drücken Sie Strg-D an der Eingabeaufforderung – es werden keinerlei Signale von bash an den Hintergrundjob gesendet.

Test:

Terminal 1

$ echo $$
16779

Terminal 2

$ strace -e signal -p16779
Process 16779 attached

(Terminal 1 schließen, in Terminal 2 gesehen):

--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16777, si_uid=3000090} ---
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_DFL, [], SA_RESTORER, 0x7f7ace3d9a00}, {0x456880, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], SA_RESTORER, 0x7f7ace3d9a00}, 8) = 0
kill(16779, SIGHUP)                     = 0
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16779, si_uid=3000090} ---
+++ killed by SIGHUP +++

Stelle doit.sh :

#!/bin/bash

imhupped() {
        echo "HUP" >> /tmp/outfile
}

trap imhupped SIGHUP

for i in $(seq 1 6); do echo out $i >> /tmp/outfile; sleep 5; done

Starten Sie es im Hintergrund im Terminal 1:

Terminal 1

$ ./doit.sh &
[1] 22954

Verfolgen Sie es in Terminal 2; schließen Sie Terminal 1 nach ein paar Schleifen:

Terminal 2

$ strace -e signal -p22954
Process 22954 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22980, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7a5d547a00}, {0x43e4b0, [], SA_RESTORER, 0x7f7a5d547a00}, 8) = 0
...
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=21685, si_uid=3000090} ---
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=23017, si_status=SIGHUP, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
...

Ausgabe in Klemme 3:

Terminal 3

out 1
out 2
out 3
HUP
out 4
out 5
out 6

Wenn Sie jedoch bash beenden , wird es einfach beendet, ohne überhaupt ein Signal an das Kind zu senden. Das Terminal wird beendet, weil es kein Kind mehr hat, aber natürlich gibt es niemanden für HUP, weil die Kind-Shell bereits weg ist. Die SIGINT , SIG_BLOCK und SIG_SETMASK die Sie unten sehen, sind auf sleep zurückzuführen in der Schale.

Terminal 1

$ ./doit.sh &
26275

Terminal 2

$ strace -e signal -p26275
Process 26275 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26280, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0


(..."exit" is typed in bash, notice no new signals sent...)


rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26303, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0

Klemme 3, Ausgang

out 1
out 2
out 3
out 4
out 5
out 6

Interessanterweise habe ich huponexit eingestellt eingeschaltet sein mit shopt -s huponexit; shopt (letzteres shopt zur Überprüfung), führte dann den letzten Test durch und wieder bash sendete kein Signal an den Hintergrundprozess . Sogar noch interessanter, wie wir gesehen haben, dass bash tat Senden Sie das Signal an den Hintergrundprozess, nachdem er es von einem Terminal empfangen hat, das ihm ins Gesicht geschlossen hat. Es scheint, als ob huponexit hatte auf die eine oder andere Weise keine Bedeutung.

Ich hoffe, dies beseitigt alle Rätsel oder Verwirrungen zumindest in Bezug auf die Freude von bash, wann und wie das HUP-Signal gesendet wird. Zumindest waren meine Tests für mich vollständig reproduzierbar. Mich würde interessieren, ob es irgendwelche anderen Einstellungen gibt, die das Verhalten von bash beeinflussen könnten.

Und wie immer YSMV (Your Shell May Vary).

Nachtrag 1

Wenn ich eine Shell als exec /bin/sh ausführe , und führen Sie das Skript dann als /bin/sh ./doit.sh & aus , dann beenden Sie die Shell sauber, es werden keine Signale an den Hintergrundjob gesendet und er wird bis zum Ende weiter ausgeführt.

Nachtrag 2

Wenn ich eine Shell als exec /bin/csh ausführe , und führen Sie das Skript dann als /bin/sh ./doit.sh & aus , dann beenden Sie die Shell sauber, es werden keine Signale an den Hintergrundjob gesendet und er wird bis zum Ende weiter ausgeführt.


Linux
  1. Was bekomme ich, wenn Sudo ein Kernel-zerstörendes Programm ist?

  2. Ich erhalte eine Fehlermeldung, wenn ich versuche, Youtube-dl in 18.04 zu aktualisieren?

  3. Ich erhalte einen 404-Fehler, wenn ich auf cPanel zugreife

  4. Commandline überschreibt sich selbst, wenn die Befehle zu lang werden

  5. Wie beendet man alle Hintergrundprozesse in zsh?

Erhalten Sie eine Benachrichtigung, wenn eine Terminalaufgabe erledigt ist

So starten Sie die Bildschirmsitzung unter Linux beim Anmelden automatisch

Tmux-Sitzung auf Remote-System automatisch starten, wenn Sie sich über SSH anmelden

Führen Sie Hintergrundprozesse in Linux mit dem Screen-Befehl aus

So senden Sie Prozesse unter Linux an den Hintergrund

Wie weist Linux Bandbreite zwischen Prozessen zu?