Für alle, die mit dem gleichen Problem konfrontiert sind: Denken Sie daran, dass Sie, selbst wenn Sie tippen yourExecutable &und die Ausgaben weiterhin auf dem Bildschirm erscheinen und Ctrl+Cnichts zu stoppen scheinen, einfach blind tippen disown;und drücken, Enterselbst wenn der Bildschirm mit den Ausgaben scrollt und Sie nicht sehen können, was Sie tippen. Der Prozess wird abgelehnt und Sie können das Terminal schließen, ohne dass der Prozess stirbt.
Nav
Antworten:
1367
Verwenden der Jobsteuerung von bash, um den Prozess in den Hintergrund zu stellen:
Ctrl+ Zum das Programm anzuhalten (anzuhalten) und zur Shell zurückzukehren.
bg um es im Hintergrund auszuführen.
disown -h [job-spec]Dabei ist [Jobspezifikation] die Jobnummer (wie %1beim ersten ausgeführten Job; ermitteln Sie Ihre Nummer mit dem jobsBefehl), damit der Job beim Schließen des Terminals nicht beendet wird.
Da die Frage lautete, wie man es unter "nohup" stellt, disown -hlautet die genauere Antwort: "Verleugnung verhalten sich eher wie nohup (dh die Jobs bleiben im Prozessbaum Ihrer aktuellen Shell, bis Sie Ihre Shell verlassen). Dies ermöglicht es Ihnen zu sehen alle Jobs, die diese Shell gestartet hat. " (von [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
Dr. Jan-Philip Gehrcke
8
Wie kann ich den Job später wiederherstellen? Ich kann es mit ps -e laufen sehen.
Paulo Casaretto
26
Sie können die Ausgabe eines Jobs nicht sehen, nachdem disowndisown einen Prozess zu einem Daemon gemacht hat. Dies bedeutet, dass die Standardeingabe / -ausgabe nach / dev / null umgeleitet wird. Wenn Sie also vorhaben, einen Job my_job_command | tee my_job.log
abzulehnen
8
ist es irgendwie möglich so etwas wie 'my_job_command | zu machen tee my_job.log ' nachdem der Befehl bereits ausgeführt wird?
Angenommen, aus irgendeinem Grund Ctrl+ Zfunktioniert auch nicht, gehen Sie zu einem anderen Terminal, suchen Sie die Prozess-ID (using ps) und führen Sie Folgendes aus:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOPwird den Prozess SIGCONTanhalten und den Prozess im Hintergrund fortsetzen. Wenn Sie jetzt beide Terminals schließen, wird Ihr Prozess nicht gestoppt.
Ja, das ist ein Betriebssystemproblem. Kill funktioniert nicht mit Cygwin unter Windows.
Pungs
6
Auch sehr nützlich, wenn der Job von einer anderen SSH-Sitzung aus gestartet wird.
Amir Ali Akbari
5
Denken Sie daran, dies disown %1im ersten Terminal zu tun, bevor Sie es schließen.
Fred
1
Dies ist nützlich, da ich eine grafische Oberfläche mit einer Konsole gestartet habe (in meinem Fall habe ich kwinnach einem Absturz von der Konsole aus gestartet, ohne an die Konsequenzen zu denken). Wenn ich also kwin gestoppt hätte, wäre alles eingefroren und ich hätte keine Möglichkeit zu rennen bg!
Michele
@fred Ich habe das nicht gemacht und es schien weiter zu laufen. Möglich oder habe ich die falsche PID getroffen?
Niemand
91
Der Befehl zum Trennen eines laufenden Jobs von der Shell (= macht ihn nohup) ist disownund 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 nicht jede Jobspezifikation 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, alle Jobs zu entfernen oder zu markieren. Die Option -r ohne das Argument jobspec beschränkt den Betrieb auf 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 eine einfache
disown -a
entfernt alle Jobs aus der Jobtabelle und macht sie nohup
disown -aentfernt alle Jobs. Ein einfaches disownentfernt nur den aktuellen Job. Wie die Manpage in der Antwort sagt.
Rune Schjellerup Philosof
73
Dies sind gute Antworten oben, ich wollte nur eine Klarstellung hinzufügen:
Sie können nicht disownpid oder verarbeiten, Sie sind disownein Job, und das ist eine wichtige Unterscheidung.
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 aussetzen) und ihn dann ablehnen.
Problem:
% jobs
[1] running java
[2] suspended vi
% disown %1
Ist leider disownspezifisch für Bash und nicht in allen Shells verfügbar.
Bestimmte Unix-Varianten (z. B. AIX und Solaris) verfügen über eine Option im nohupBefehl selbst, die auf einen laufenden Prozess angewendet werden kann:
Nur für AIXund Solaris. "Die AIX- und Solaris-Versionen von nohup verfügen über die Option -p, mit der ein laufender Prozess so geändert wird, dass zukünftige SIGHUP-Signale ignoriert werden. Im Gegensatz zu dem oben beschriebenen nicht verleugneten Build von bash akzeptiert nohup -p Prozess-IDs." Quelle
AlikElzin-kilaka
27
Die Antwort von Node ist wirklich großartig, aber es blieb die Frage offen, wie stdout und stderr umgeleitet werden können. Ich habe eine Lösung unter Unix und Linux gefunden , die aber auch nicht vollständig ist. 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 druckt.
$./loop.sh
Holen Sie sich jetzt irgendwie die PID dieses Prozesses. Normalerweise ps -C loop.shist es gut genug, aber es ist in meinem Fall gedruckt.
Jetzt können wir zu einem anderen Terminal wechseln (oder ^ Z und im selben Terminal drücken). Nun gdbsollte an diesen Prozess angehängt werden.
$ gdb -p <PID>
Dies stoppt das Skript (falls ausgeführt). Sein Zustand kann überprüft werden durch ps -f <PID>, wobei das STATFeld '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 mit open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). Anstelle von O_RDWRO_WRONLYkönnte angewendet werden, /usr/sbin/lsofsagt aber 'u' für alle std * -Dateihandler ( FDSpalte), das heißt O_RDWR.
Ich habe die Werte in der Header-Datei /usr/include/bits/fcntl.h überprüft.
Die Ausgabedatei könnte wie gewohnt geöffnet werden O_APPEND, nohupdies wird jedoch man open(2)aufgrund möglicher NFS-Probleme nicht empfohlen .
Wenn wir -1 als Rückgabewert erhalten, wird call perror("")die Fehlermeldung ausgegeben. Wenn wir den Fehler benötigen, verwenden Sie den Befehl p errnogdb.
Jetzt können wir die neu umgeleitete Datei überprüfen. /usr/sbin/lsof -p <PID>Drucke:
Wenn wir möchten, können wir stderr in eine andere Datei umleiten, wenn wir einen anderen Dateinamen verwenden call close(2)und call open(...)erneut verwenden möchten .
Jetzt muss der Anhang bashfreigegeben werden und wir können aufhören gdb:
(gdb) detach
Detaching from program:/bin/bash, process <PID>(gdb) q
Wenn das Skript gdbvon einem anderen Terminal aus 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. Also drück ^Z.
^Z
[1]+Stopped./loop.sh
(Jetzt sind wir in dem Zustand, als ob ^Zam 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>011:16 pts/36 S 0:00/bin/bash ./loop.sh
$ jobs
[1]+Stopped./loop.sh
Der Prozess sollte also im Hintergrund ausgeführt und vom Terminal getrennt werden. Die Zahl in der jobsAusgabe des Befehls in eckigen Klammern kennzeichnet den darin enthaltenen Job bash. Wir können in den folgenden integrierten bashBefehlen 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>011:16 pts/36 S 0:00/bin/bash ./loop.sh
Und jetzt können wir die Calling Bash beenden. Der Prozess läuft im Hintergrund weiter. Wenn wir die 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>1011:16? S 0:00/bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>...
loop.sh <PID> truey 0u CHR 136,3638/dev/pts/36(deleted)
loop.sh <PID> truey 1u REG 0,26112715008411/home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,3638/dev/pts/36(deleted)
KOMMENTAR
Das GDB-Zeug kann automatisiert werden, indem eine Datei (z. B. loop.gdb) erstellt wird, die die Befehle enthält, und ausgeführt werden gdb -q -x loop.gdb -p <PID>. Meine loop.gdb sieht folgendermaßen aus:
Sehr informativ und funktioniert wahrscheinlich in einfachen Fällen gut. Aber seien Sie gewarnt, komplexere Fälle können kläglich scheitern. Ich hatte heute einen davon: Mein Prozess hatte einen anderen Prozess ausgelöst, der die Ausgabe (vermutlich an stderr) ausführte, aber stdout für die Kommunikation mit seinem Master angeschlossen. Das Umleiten der Master-FDs war effektiv, da das Kind stderr geerbt hatte, und das Schließen des Childs-stdout schlug fehl, wenn der Master am anderen Ende der Pipe wartete. X- | Bettern kennt Ihre Prozesse gut, bevor Sie dies versuchen.
cmaster - wieder einsetzen Monica
@cmaster Sie können überprüfen, ob ein Handle umgeleitet wird, indem lsof(der Name des Datei- Handles ist pipenicht wie /dev/pts/1) oder von ls -l /proc/<PID>/fd/<fd>(dies zeigt den Symlink des Handles). Auch Unterprozesse können immer noch keine umgeleiteten Ausgaben haben, die in eine Datei umgeleitet werden sollten.
Dann habe ich die folgenden Befehle ausprobiert und es hat sehr gut funktioniert
Führen Sie beispielsweise SOMECOMMAND aus /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1.
Ctrl+ Zum das Programm anzuhalten (anzuhalten) und zur Shell zurückzukehren.
bg um es im Hintergrund auszuführen.
disown -h Damit der Prozess beim Schließen des Terminals nicht abgebrochen wird.
Geben Sie ein exit, um die Shell zu verlassen, da Sie jetzt loslegen können, da der Vorgang in einem eigenen Prozess im Hintergrund ausgeführt wird, sodass er nicht an eine Shell gebunden ist.
Dieser Vorgang entspricht dem Ausführen nohup SOMECOMMAND.
Das hat gut funktioniert. Mein Prozess wurde auch nach dem Schließen der Terminalfenster fortgesetzt. Wir haben ksh als Standard-Shell, daher funktionierten die Befehle bgund disownnicht.
Ich denke, das Verhalten für Verleugnung -a besteht darin, die Bindung an alle Jobs zu verringern. Die stdin / stdout-Pipelines werden jedoch nicht heruntergefahren, was bedeutet, dass der Prozess weiterhin versucht, vom Terminal aus zu schreiben (/ zu lesen)
Kelthar,
-2
Dies funktionierte für mich unter Ubuntu Linux, während ich in tcshell war.
yourExecutable &
und die Ausgaben weiterhin auf dem Bildschirm erscheinen undCtrl+C
nichts zu stoppen scheinen, einfach blind tippendisown;
und drücken,Enter
selbst wenn der Bildschirm mit den Ausgaben scrollt und Sie nicht sehen können, was Sie tippen. Der Prozess wird abgelehnt und Sie können das Terminal schließen, ohne dass der Prozess stirbt.Antworten:
Verwenden der Jobsteuerung von bash, um den Prozess in den Hintergrund zu stellen:
bg
um es im Hintergrund auszuführen.disown -h [job-spec]
Dabei ist [Jobspezifikation] die Jobnummer (wie%1
beim ersten ausgeführten Job; ermitteln Sie Ihre Nummer mit demjobs
Befehl), damit der Job beim Schließen des Terminals nicht beendet wird.quelle
disown -h
lautet die genauere Antwort: "Verleugnung verhalten sich eher wie nohup (dh die Jobs bleiben im Prozessbaum Ihrer aktuellen Shell, bis Sie Ihre Shell verlassen). Dies ermöglicht es Ihnen zu sehen alle Jobs, die diese Shell gestartet hat. " (von [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )disown
disown einen Prozess zu einem Daemon gemacht hat. Dies bedeutet, dass die Standardeingabe / -ausgabe nach / dev / null umgeleitet wird. Wenn Sie also vorhaben, einen Jobmy_job_command | tee my_job.log
disown
Trennt alle Rohre vom Prozess. Verwenden Siegdb
zum Wiederanbringen von Rohren wie in diesem Gewinde beschrieben . Genauer gesagt, dieser Beitrag .Angenommen, aus irgendeinem Grund Ctrl+ Zfunktioniert auch nicht, gehen Sie zu einem anderen Terminal, suchen Sie die Prozess-ID (using
ps
) und führen Sie Folgendes aus:SIGSTOP
wird den ProzessSIGCONT
anhalten und den Prozess im Hintergrund fortsetzen. Wenn Sie jetzt beide Terminals schließen, wird Ihr Prozess nicht gestoppt.quelle
disown %1
im ersten Terminal zu tun, bevor Sie es schließen.kwin
nach einem Absturz von der Konsole aus gestartet, ohne an die Konsequenzen zu denken). Wenn ich also kwin gestoppt hätte, wäre alles eingefroren und ich hätte keine Möglichkeit zu rennenbg
!Der Befehl zum Trennen eines laufenden Jobs von der Shell (= macht ihn nohup) ist
disown
und ein grundlegender Shell-Befehl.Aus der Bash-Manpage (Man Bash):
Das heißt, dass eine einfache
entfernt alle Jobs aus der Jobtabelle und macht sie nohup
quelle
disown -a
entfernt alle Jobs. Ein einfachesdisown
entfernt nur den aktuellen Job. Wie die Manpage in der Antwort sagt.Dies sind gute Antworten oben, ich wollte nur eine Klarstellung hinzufügen:
Sie können nicht
disown
pid oder verarbeiten, Sie sinddisown
ein Job, und das ist eine wichtige Unterscheidung.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 aussetzen) und ihn dann ablehnen.
Problem:
Weitere Informationen zur Unix-Jobsteuerung finden Sie unter http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ .
quelle
Ist leider
disown
spezifisch für Bash und nicht in allen Shells verfügbar.Bestimmte Unix-Varianten (z. B. AIX und Solaris) verfügen über eine Option im
nohup
Befehl selbst, die auf einen laufenden Prozess angewendet werden kann:Siehe http://en.wikipedia.org/wiki/Nohup
quelle
AIX
undSolaris
. "Die AIX- und Solaris-Versionen von nohup verfügen über die Option -p, mit der ein laufender Prozess so geändert wird, dass zukünftige SIGHUP-Signale ignoriert werden. Im Gegensatz zu dem oben beschriebenen nicht verleugneten Build von bash akzeptiert nohup -p Prozess-IDs." QuelleDie Antwort von Node ist wirklich großartig, aber es blieb die Frage offen, wie stdout und stderr umgeleitet werden können. Ich habe eine Lösung unter Unix und Linux gefunden , die aber auch nicht vollständig ist. 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 druckt.
Holen Sie sich jetzt irgendwie die PID dieses Prozesses. Normalerweise
ps -C loop.sh
ist es gut genug, aber es ist in meinem Fall gedruckt.Jetzt können wir zu einem anderen Terminal wechseln (oder ^ Z und im selben Terminal drücken). Nun
gdb
sollte an diesen Prozess angehängt werden.Dies stoppt das Skript (falls ausgeführt). Sein Zustand kann überprüft werden durch
ps -f <PID>
, wobei dasSTAT
Feld 'T +' ist (oder im Fall von ^ Z 'T'), was bedeutet (man ps (1))Close (1) gibt bei Erfolg Null zurück.
Open (1) gibt bei Erfolg den neuen Dateideskriptor zurück.
Diese Öffnung ist gleich mit
open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. Anstelle vonO_RDWR
O_WRONLY
könnte angewendet werden,/usr/sbin/lsof
sagt aber 'u' für alle std * -Dateihandler (FD
Spalte), das heißtO_RDWR
.Ich habe die Werte in der Header-Datei /usr/include/bits/fcntl.h überprüft.
Die Ausgabedatei könnte wie gewohnt geöffnet werden
O_APPEND
,nohup
dies wird jedochman open(2)
aufgrund möglicher NFS-Probleme nicht empfohlen .Wenn wir -1 als Rückgabewert erhalten, wird
call perror("")
die Fehlermeldung ausgegeben. Wenn wir den Fehler benötigen, verwenden Sie den Befehlp errno
gdb.Jetzt können wir die neu umgeleitete Datei überprüfen.
/usr/sbin/lsof -p <PID>
Drucke:Wenn wir möchten, können wir stderr in eine andere Datei umleiten, wenn wir einen anderen Dateinamen verwenden
call close(2)
undcall open(...)
erneut verwenden möchten .Jetzt muss der Anhang
bash
freigegeben werden und wir können aufhörengdb
:Wenn das Skript
gdb
von einem anderen Terminal aus 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. Also drück^Z
.(Jetzt sind wir in dem Zustand, als ob
^Z
am Anfang gedrückt wurde.)Jetzt können wir den Status des Jobs überprüfen:
Der Prozess sollte also im Hintergrund ausgeführt und vom Terminal getrennt werden. Die Zahl in der
jobs
Ausgabe des Befehls in eckigen Klammern kennzeichnet den darin enthaltenen Jobbash
. Wir können in den folgenden integriertenbash
Befehlen ein '%' - Zeichen vor der Jobnummer verwenden:Und jetzt können wir die Calling Bash beenden. Der Prozess läuft im Hintergrund weiter. Wenn wir die PPID beenden, wird 1 (init (1) -Prozess) und das Steuerterminal wird unbekannt.
KOMMENTAR
Das GDB-Zeug kann automatisiert werden, indem eine Datei (z. B. loop.gdb) erstellt wird, die die Befehle enthält, und ausgeführt werden
gdb -q -x loop.gdb -p <PID>
. Meine loop.gdb sieht folgendermaßen aus:Oder man kann stattdessen den folgenden Liner verwenden:
Ich hoffe, dies ist eine ziemlich vollständige Beschreibung der Lösung.
quelle
lsof
(der Name des Datei- Handles istpipe
nicht wie/dev/pts/1
) oder vonls -l /proc/<PID>/fd/<fd>
(dies zeigt den Symlink des Handles). Auch Unterprozesse können immer noch keine umgeleiteten Ausgaben haben, die in eine Datei umgeleitet werden sollten.So senden Sie den laufenden Prozess an nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
Bei mir hat es nicht geklapptDann habe ich die folgenden Befehle ausprobiert und es hat sehr gut funktioniert
Führen Sie beispielsweise SOMECOMMAND aus
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.Ctrl+ Zum das Programm anzuhalten (anzuhalten) und zur Shell zurückzukehren.
bg
um es im Hintergrund auszuführen.disown -h
Damit der Prozess beim Schließen des Terminals nicht abgebrochen wird.Geben Sie ein
exit
, um die Shell zu verlassen, da Sie jetzt loslegen können, da der Vorgang in einem eigenen Prozess im Hintergrund ausgeführt wird, sodass er nicht an eine Shell gebunden ist.Dieser Vorgang entspricht dem Ausführen
nohup SOMECOMMAND
.quelle
Auf meinem AIX-System habe ich es versucht
Das hat gut funktioniert. Mein Prozess wurde auch nach dem Schließen der Terminalfenster fortgesetzt. Wir haben ksh als Standard-Shell, daher funktionierten die Befehle
bg
unddisown
nicht.quelle
bg
- Dadurch wird der Job in den Hintergrund gestellt und im laufenden Prozess zurückgegebendisown -a
- Dadurch wird der gesamte Anhang mit dem Job abgeschnitten (sodass 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 aktiviert
nohup
(basierend auf meinem Verständnis Ihrer Frage, brauchen Sie es hier nicht).quelle
Dies funktionierte für mich unter Ubuntu Linux, während ich in tcshell war.
CtrlZ um es anzuhalten
bg
im Hintergrund laufenjobs
um seine Jobnummer zu bekommennohup %n
Dabei ist n die Auftragsnummerquelle
nohup: failed to run command '%1': No such file or directory