shell - titel - wordpress title startseite




Wie stelle ich einen bereits laufenden Prozess unter nohup? (7)

Ich habe einen Prozess, der schon lange läuft und nicht enden will.

Wie stelle ich es unter nohup (das heißt, wie führe ich es weiter, selbst wenn ich das Terminal schließe?)


  1. Strg + Z - das wird den Job pausieren (nicht abbrechen!)
  2. bg - dies versetzt den Job in den Hintergrund und kehrt im laufenden Prozess zurück
  3. disown -a - dies wird den gesamten Anhang mit Job schneiden (damit Sie das Terminal schließen können und es noch läuft)

Mit diesen einfachen Schritten können Sie das Terminal schließen, während der Prozess läuft.

Es wird nicht nohup (basierend auf meinem Verständnis Ihrer Frage, Sie brauchen es hier nicht).


Angenommen, aus irgendeinem Grund funktioniert auch Strg + Z nicht, gehen Sie zu einem anderen Terminal, suchen Sie die Prozess-ID (mit ps ) und führen Sie ps aus:

kill -20 PID 
kill -18 PID

kill -20 ( SIGTSTP ) wird den Prozess SIGCONT und kill -18 ( SIGCONT ) wird den Prozess im Hintergrund fortsetzen. Wenn Sie also beide Terminals schließen, wird Ihr Prozess nicht gestoppt.


Der Befehl zum Trennen eines laufenden Jobs von der Shell (= macht es nohup) wird disown und ein einfacher Shell-Befehl.

Von Bash-Manpage (Mann bash):

verleugnen [-ar] [-h] [jobspec ...]

Ohne Optionen wird jede Jobspec aus der Tabelle der aktiven Jobs entfernt. Wenn die Option -h angegeben wird, wird jede Jobspezifikation nicht aus der Tabelle entfernt, sondern markiert, sodass SIGHUP nicht an den Job gesendet wird, wenn die Shell eine SIGHUP empfängt. Wenn keine Jobspezifikation vorhanden ist und weder die Option -a noch die Option -r angegeben wird, wird der aktuelle Job verwendet. Wenn keine Jobspezifikation bereitgestellt wird, bedeutet die Option -a das Entfernen oder Markieren aller Jobs. Die Option -r ohne ein Jobspec-Argument beschränkt die Operation auf laufende Jobs. Der Rückgabewert ist 0, es sei denn, eine Jobspezifikation gibt keinen gültigen Job an.

Das bedeutet, dass ein einfaches

disown -a

Entfernt alle Jobs aus der Job-Tabelle und macht sie nohup


Die Antwort von Node ist wirklich großartig, aber es hat die Frage offen gelassen, wie man stdout und stderr umleiten kann. Ich habe unter Unix & Linux eine Lösung gefunden, aber sie ist auch nicht vollständig. Ich möchte diese beiden Lösungen zusammenführen. Hier ist es:

Für meinen Test habe ich ein kleines Bash-Skript namens loop.sh erstellt, das die PID von sich selbst mit einem winzigen Schlaf in einer Endlosschleife druckt.

$./loop.sh

Bekommen Sie jetzt die PID dieses Prozesses irgendwie. Normalerweise ps -C loop.sh ist gut genug, aber es ist in meinem Fall gedruckt.

Jetzt können wir zu einem anderen Terminal wechseln (oder drücken Sie ^ Z und im selben Terminal). Nun sollte gdb an diesen Prozess angehängt werden.

$ gdb -p <PID>

Dies stoppt das Skript (wenn es ausgeführt wird). Sein Zustand kann mit ps -f <PID> überprüft werden, wobei das STAT Feld 'T +' (oder im Fall von 'Z' T ') ist, was bedeutet (man ps (1))

    T Stopped, either by a job control signal or because it is being traced
    + is in the foreground process group

(gdb) call close(1)
$1 = 0

Close (1) gibt bei Erfolg Null zurück.

(gdb) call open("loop.out", 01102, 0600)
$6 = 1

Open (1) gibt bei Erfolg den neuen Dateideskriptor zurück.

Dieses Öffnen ist gleich dem open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR) . Anstelle von O_RDWR könnte O_WRONLY angewendet werden, aber /usr/sbin/lsof sagt 'u' für alle std * O_RDWR ( FD Spalte), was O_RDWR .

Ich habe die Werte in der Headerdatei /usr/include/bits/fcntl.h überprüft.

Die Ausgabedatei könnte mit O_APPEND geöffnet O_APPEND , wie es nohup tun würde, aber dies wird von man open(2) wegen möglicher NFS-Probleme nicht vorgeschlagen.

Wenn wir -1 als Rückgabewert erhalten, gibt der call perror("") die Fehlermeldung aus. Wenn wir das errno brauchen, benutze p errno gdb comand.

Jetzt können wir die neu umgeleitete Datei überprüfen. /usr/sbin/lsof -p <PID> druckt:

loop.sh <PID> truey    1u   REG   0,26        0 15008411 /home/truey/loop.out

Wenn wir wollen, können wir stderr in eine andere Datei umleiten, wenn wir call close(2) und call open(...) mit einem anderen Dateinamen call close(2) wollen.

Nun muss der angehängte bash freigegeben werden und wir können gdb beenden:

(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q

Wenn das Skript von einem anderen Terminal mit gdb gestoppt wurde, wird es weiter ausgeführt. Wir können zurück zum Terminal von loop.sh wechseln. Jetzt schreibt es nichts mehr auf den Bildschirm, sondern läuft und schreibt in die Datei. Wir müssen es in den Hintergrund stellen. Drücken Sie also ^Z

^Z
[1]+  Stopped                 ./loop.sh

(Jetzt sind wir in demselben Zustand, als ob ^Z am Anfang gedrückt wurde.)

Jetzt können wir den Status des Jobs überprüfen:

$ ps -f 24522
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh
$ jobs
[1]+  Stopped                 ./loop.sh

Der Prozess sollte also im Hintergrund laufen und vom Terminal getrennt sein. Die Nummer in der Ausgabe des Jobbefehls in eckigen Klammern identifiziert den Job innerhalb der bash . Wir können in den folgenden eingebauten bash Befehlen ein '%' Zeichen vor der Jobnummer verwenden:

$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh

Und jetzt können wir die Calling Bash verlassen. Der Prozess wird weiterhin im Hintergrund ausgeführt. Wenn wir seine PPID beenden, wird 1 (init (1) -Prozess) und das Steuerterminal wird unbekannt.

$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID>     1  0 11:16 ?        S      0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey    0u   CHR 136,36                38 /dev/pts/36 (deleted)
loop.sh <PID> truey    1u   REG   0,26     1127 15008411 /home/truey/loop.out
loop.sh <PID> truey    2u   CHR 136,36                38 /dev/pts/36 (deleted)

KOMMENTAR

Das gdb-Zeug kann automatisiert werden, indem man eine Datei (zB loop.gdb) erzeugt, die die Befehle enthält, und gdb -q -x loop.gdb -p <PID> . Meine loop.gdb sieht folgendermaßen aus:

call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit

Oder man kann stattdessen den folgenden Liner verwenden:

gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>

Ich hoffe, dies ist eine ziemlich vollständige Beschreibung der Lösung.


Dies sind gute Antworten oben, ich wollte nur eine Klarstellung hinzufügen:

Sie können eine PID oder einen Prozess nicht disown , Sie disown einen Job ab, und das ist ein wichtiger Unterschied.

Ein Job ist eine Vorstellung von einem Prozess, der an eine Shell angehängt ist. Daher müssen Sie den Job in den Hintergrund werfen (nicht anhalten) und ihn dann ablehnen.

Problem:

%  jobs
[1]  running java 
[2]  suspended vi
%  disown %1

Eine detailliertere Diskussion über Unix Job Control finden Sie unter http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ .


Laufenden Prozess an nohup senden ( http://en.wikipedia.org/wiki/Nohup )

nohup -p pid , es hat nicht für mich funktioniert

Dann habe ich die folgenden Befehle ausprobiert und es hat sehr gut funktioniert

  1. Führen Sie SOMECOMMAND aus, sagen Sie /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1 .

  2. Strg + Z , um das Programm zu stoppen (pausieren) und zurück zur Shell zu gelangen.

  3. bg , um es im Hintergrund laufen zu lassen.

  4. disown -h damit der Prozess nicht beendet wird, wenn das Terminal geschlossen wird.

  5. Geben Sie exit , um die Shell zu verlassen, denn jetzt können Sie loslegen, da die Operation in ihrem eigenen Prozess im Hintergrund ausgeführt wird und nicht an eine Shell gebunden ist.

Dieser Prozess entspricht dem Ausführen von nohup SOMECOMMAND .


Unglücklicherweise ist Verweigerung spezifisch für bash und nicht in allen Shells verfügbar.

Bestimmte Unix-Varianten (z. B. AIX und Solaris) haben eine Option für den nohup Befehl selbst, die auf einen laufenden Prozess angewendet werden kann:

nohup -p pid

Siehe http://en.wikipedia.org/wiki/Nohup





nohup