it-swarm.com.de

Wie stelle ich einen bereits laufenden Prozess unter nohup?

Ich habe einen Prozess, der schon lange läuft und möchte ihn nicht beenden.

Wie setze ich es unter Nohup (das heißt, wie kann ich dafür sorgen, dass es weiterläuft, auch wenn ich das Terminal schließe?)

878
flybywire

Verwenden Sie Job Control von bash, um den Prozess in den Hintergrund zu stellen:

  1. Ctrl+Z um das Programm anzuhalten (anzuhalten) und zur Shell zurückzukehren.
  2. bg, um es im Hintergrund auszuführen.
  3. disown -h [job-spec] wobei [job-spec] die Jobnummer ist (wie %1 für den ersten ausgeführten Job; ermitteln Sie Ihre Nummer mit dem Befehl jobs), damit der Job nicht abgebrochen wird, wenn Das Terminal wird geschlossen.
1297
Node

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

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOP unterbricht den Prozess und SIGCONT setzt den Prozess im Hintergrund fort. Wenn Sie jetzt beide Terminals schließen, wird Ihr Prozess nicht gestoppt.

166
Pungs

Der Befehl zum Trennen eines laufenden Jobs von der Shell (= macht es zu Nohup) ist disown und ein grundlegender Shell-Befehl.

Aus der bash-manpage (man bash):

disown [-ar] [-h] [jobspec ...]

Ohne Optionen wird jede Jobspezifikation aus der Tabelle der aktiven Jobs entfernt. Wenn die Option -h angegeben ist, wird jede Jobspezifikation nicht aus der Tabelle entfernt, sondern markiert, damit SIGHUP nicht an den Job gesendet wird, wenn die Shell ein SIGHUP empfängt. Wenn keine Jobspezifikation vorhanden ist und weder die Option -a noch die Option -r angegeben sind, wird der aktuelle Job verwendet. Wenn keine Jobspezifikation angegeben ist, bedeutet die Option -a, dass alle Jobs entfernt oder markiert werden. Die Option -r ohne Jobspec-Argument beschränkt die Ausführung von Jobs. Der Rückgabewert ist 0, es sei denn, eine Jobspezifikation gibt keinen gültigen Job an.

Das heißt, dass ein einfaches

disown -a

entfernt alle Jobs aus der Jobtabelle und macht sie zu Nohup

85
serioys sam

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

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

Ein Job ist eine Idee eines Prozesses, 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

Unter http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ finden Sie weitere Informationen zur Unix-Jobsteuerung.

70
Q Boiler

Leider ist disown spezifisch für Bash und nicht in allen Shells verfügbar.

Bestimmte Unix-Versionen (z. B. AIX und Solaris) verfügen über eine Option für den Befehl Nohup, die auf einen laufenden Prozess angewendet werden kann:

Nohup -p pid

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

44
Dale

Die Antwort von Node ist wirklich großartig, hat aber die Frage offen gelassen, wie stdout und stderr umgeleitet werden können. Ich habe eine Lösung auf nix & Linux 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 einer Minute Schlaf in einer Endlosschleife ausgibt.

$./loop.sh

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

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

$ gdb -p <PID>

Dies stoppt das Skript (falls ausgeführt). Sein Zustand kann durch ps -f <PID> überprüft werden, wobei das STAT -Feld 'T +' ist (oder im Fall von ^ Z 'T'), 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.

Diese Öffnung ist gleich open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). Anstelle von O_RDWR könnte auch O_WRONLY angewendet werden, aber /usr/sbin/lsof sagt 'u' für alle std * -Dateibehandler (Spalte FD). Dies ist O_RDWR.

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

Die Ausgabedatei könnte mit O_APPEND geöffnet werden, 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 call perror("") die Fehlermeldung aus. Wenn wir die Fehlernummer benötigen, verwenden Sie den Befehl p errno gdb.

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 möchten, können wir stderr in eine andere Datei umleiten, wenn wir call close(2) und call open(...) erneut mit einem anderen Dateinamen verwenden möchten.

Nun muss das 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 durch gdb angehalten wurde, wird es weiterhin ausgeführt. Wir können zurück zum Terminal von loop.sh wechseln. Jetzt wird nichts mehr auf den Bildschirm geschrieben, sondern ausgeführt und in die Datei geschrieben. Wir müssen es in den Hintergrund stellen. Drücken Sie also ^Z.

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

(Jetzt befinden wir uns in dem Zustand, in dem ^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 daher im Hintergrund ausgeführt und vom Terminal getrennt werden. Die Zahl in der Ausgabe des Befehls jobs in eckigen Klammern kennzeichnet den Job in bash. Wir können in den folgenden eingebauten bash Befehlen ein% -Zeichen vor der Auftragsnummer 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 anrufende Bash beenden. Der Prozess läuft im Hintergrund weiter. Wenn wir seine PPID verlassen, 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)

COMMENT

Das gdb-Zeug kann automatisiert werden, indem eine Datei (z. B. loop.gdb) erstellt wird, die die Befehle enthält, und gdb -q -x loop.gdb -p <PID> ausgeführt wird. Meine loop.gdb sieht so 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 einen 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.

24
TrueY

So senden Sie einen laufenden Prozess an Nohup ( http://en.wikipedia.org/wiki/Nohup )

Nohup -p pid, es hat bei mir nicht 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. Ctrl+Z um das Programm anzuhalten (anzuhalten) und zur Shell zurückzukehren.

  3. bg, um es im Hintergrund auszuführen.

  4. disown -h, damit der Vorgang beim Schließen des Terminals nicht abgebrochen wird.

  5. Geben Sie exit ein, um die Shell zu verlassen. Jetzt können Sie loslegen, da der Vorgang in einem eigenen Prozess im Hintergrund ausgeführt wird und nicht an eine Shell gebunden ist.

Dieser Prozess entspricht der Ausführung von Nohup SOMECOMMAND.

7
minhas23

Auf meinem AIX-System habe ich es versucht

Nohup -p  processid>

Das hat gut funktioniert. Mein Prozess wurde auch nach dem Schließen der Terminalfenster weiter ausgeführt. Wir haben ksh als Standard-Shell, daher haben die Befehle bg und disown nicht funktioniert.

2
guest
  1. ctrl + z - Dadurch wird der Auftrag angehalten (wird nicht abgebrochen!)
  2. bg - Damit wird der Job in den Hintergrund gestellt und kehrt in den laufenden Prozess zurück
  3. disown -a - Hiermit wird der gesamte Anhang mit dem Auftrag abgeschnitten (so dass Sie das Terminal schließen können und es weiterhin ausgeführt wird).

Mit diesen einfachen Schritten können Sie das Terminal schließen, während der Prozess ausgeführt wird.

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

1
hi-zir

Dies funktionierte für mich unter Ubuntu Linux, während ich in tcshell war.

  1. CtrlZ um es anzuhalten

  2. bg um im Hintergrund zu laufen

  3. jobs, um die Auftragsnummer abzurufen

  4. Nohup %n wobei n die Auftragsnummer ist

0
eshaya