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 dem jobs
Befehl), damit der Job beim Schließen des Terminals nicht beendet wird.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 Job my_job_command | tee my_job.log
disown
Trennt alle Rohre vom Prozess. Verwenden Sie gdb
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:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
wird den Prozess SIGCONT
anhalten und den Prozess im Hintergrund fortsetzen. Wenn Sie jetzt beide Terminals schließen, wird Ihr Prozess nicht gestoppt.
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 rennen bg
!
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):
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 -a
entfernt alle Jobs. Ein einfaches disown
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 sind disown
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:
% jobs
[1] running java
[2] suspended vi
% disown %1
Weitere Informationen zur Unix-Jobsteuerung finden Sie unter http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ .
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:
nohup -p pid
AIX
und 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
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.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.
$ gdb -p <PID>
Dies stoppt das Skript (falls ausgeführt). Sein Zustand kann überprüft werden durch ps -f <PID>
, 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 mit open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. Anstelle von O_RDWR
O_WRONLY
könnte angewendet werden, /usr/sbin/lsof
sagt aber 'u' für alle std * -Dateihandler ( FD
Spalte), 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
, nohup
dies 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 errno
gdb.
Jetzt können wir die neu umgeleitete Datei überprüfen. /usr/sbin/lsof -p <PID>
Drucke:
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 einen anderen Dateinamen verwenden call close(2)
und call open(...)
erneut verwenden möchten .
Jetzt muss der Anhang bash
freigegeben werden und wir können aufhören gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
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
.
^Z
[1]+ Stopped ./loop.sh
(Jetzt sind wir in dem 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 ausgeführt und vom Terminal getrennt werden. Die Zahl in der jobs
Ausgabe des Befehls in eckigen Klammern kennzeichnet den darin enthaltenen Job bash
. Wir können in den folgenden integrierten 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 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> 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 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:
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.
lsof
(der Name des Datei- Handles ist pipe
nicht 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.
So senden Sie den laufenden Prozess an nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
Bei mir hat es nicht geklappt
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
.
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).
Dies funktionierte für mich unter Ubuntu Linux, während ich in tcshell war.
CtrlZ um es anzuhalten
bg
im Hintergrund laufen
jobs
um seine Jobnummer zu bekommen
nohup %n
Dabei ist n die Auftragsnummer
nohup: failed to run command '%1': No such file or directory
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.