Wenn ich es überprüfe ps aux | grep long_process, es wird kein Prozess ausgeführt.
long_process.py die weiterhin Text druckt: kein Ausgang.
Mache ich hier etwas falsch?
Können Sie ein Minimalbeispiel posten, das nicht funktioniert? Nach einem trivialen python -c 'import subprocess; subprocess.Popen(["sleep", "60"])' die Ausgabe von ps zeigt, dass die sleep läuft gut weiter, nachdem Python beendet wurde.
– Benutzer4815162342
23. Dezember 2014 um 17:15 Uhr
Sie führen Python mit einem einzigen Argument aus, "nohup /usr/bin/python25 ...", was nicht funktionieren kann, weil die python Ausführbare Datei sucht nach einem Skript in einer Datei mit dem genauen Namen nohup /usr/bin/..., die es nicht gibt. Und da Sie angeben stderr wie PIPE ohne jemals den Inhalt der Pipe zu lesen, bekommen Sie die Fehlermeldung nie zu sehen. Verliere die nohup und &, und einfach laufen subprocess.Popen([sys.executable, "/.../long_process.py"]). Auch nicht angeben stdin und stderr als Rohre, es sei denn, Sie meinen es so.
– Benutzer4815162342
23. Dezember 14 um 17:21 Uhr
nohup am sinnvollsten, wenn Sie einen Prozess von einer Shell aus starten. Ich sehe nicht shell=True in deinem Popen Anruf.
– 9000
23. Dezember 14 um 17:42 Uhr
9000
Sie öffnen Ihren lang andauernden Prozess und halten Sie eine Pfeife dazu. Sie erwarten also, mit ihm zu sprechen. Wenn Ihr Launcher-Skript beendet wird, können Sie nicht mehr mit ihm sprechen. Der lang andauernde Prozess erhält a SIGPIPE und Ausgänge.
Folgendes hat nur für mich funktioniert (Linux, Python 2.7).
Erstellen Sie eine lang laufende ausführbare Datei:
$ echo "sleep 100" > ~/tmp/sleeper.sh
Führen Sie Python REPL aus:
$ python
>>>
import subprocess
import os
p = subprocess.Popen(['/bin/sh', os.path.expanduser('~/tmp/sleeper.sh')])
# look ma, no pipes!
print p.pid
# prints 29893
Beenden Sie die REPL und sehen Sie, wie der Prozess noch läuft:
Wenn Sie zuerst mit dem gestarteten Prozess kommunizieren und ihn dann alleine weiterlaufen lassen möchten, haben Sie einige Möglichkeiten:
Handhaben SIGPIPE Sterben Sie in Ihrem lang andauernden Prozess nicht daran. Live ohne stdin, nachdem der Launcher-Prozess beendet wurde.
Übergeben Sie alles, was Sie wollten, mit Argumenten, Umgebung oder einer temporären Datei.
Wenn Sie eine bidirektionale Kommunikation wünschen, sollten Sie die Verwendung einer benannten Pipe (Mann mkfifo) oder einen Socket oder das Schreiben eines richtigen Servers.
Verzweigen Sie den lang andauernden Prozess, nachdem die anfängliche bidirektionale Kommunikationsphase abgeschlossen ist.
Tolle Antwort, es ist ein guter Punkt, an dem der Prozess stirbt SIGPIPE. (Im Code aus der Frage wurde der Prozess nie gestartet, aber das OP hat möglicherweise auch andere Varianten ausprobiert, die gestartet wurden und aufgrund von gestorben sind SIGPIPE.)
– Benutzer4815162342
23. Dezember 2014 um 19:50 Uhr
Es entsteht kein “völlig unabhängiger Prozess” (das was python-daemon Paket tut). Außerdem wird ein untergeordneter Prozess SIGPIPE in Python 2 nicht erhalten. In einfachen Fällen reicht Ihre Lösung jedoch aus (Sie sollten auf os.devnull stdin/stdout/stderr des Kindes, um das Warten auf Eingaben und/oder eine falsche Ausgabe an das Terminal zu vermeiden).
– jfs
23. Dezember 2014 um 20:35 Uhr
@ user4815162342: Es stirbt nicht aufgrund von SIGPIPE in Python 2 (die Frage hat das Tag python2.7).
– jfs
23. Dezember 14 um 20:37 Uhr
Hier ist ein Beispiel dafür, warum die Umleitung wichtig ist: Sie kann es einem übergeordneten Prozess ermöglichen, sich zu beenden, bevor sein untergeordneter Prozess seine Ausgabe fertig geschrieben hat: Python subprocess .check_call vs .check_output
– jfs
14. November 20 um 6:22 Uhr
Sie können verwenden os.fork().
import os
pid=os.fork()
if pid==0: # new process
os.system("nohup python ./myfile.py &")
exit()
# parent process continues
Beachten Sie, dass os.fork() existiert nicht für Windows
– Pro Q
13. Oktober 18 um 8:34 Uhr
Verwenden nohup hier ist sinnlos. Es macht genau zwei Dinge: (1) Deaktivieren der HUP-Weitergabe, das heißt schon für nicht interaktive Shells deaktiviert und muss daher nicht weiter deaktiviert werden; und (2) stdin, stdout und stderr umleiten, wenn sie an das Terminal angeschlossen sind (was Sie trivial selbst tun können; </dev/null >nohup.out 2>&1 und Sie haben genau die gleichen Umleitungen gemacht, die nohup machen würde). Es ist viel effizienter, alle Schalen ganz wegzulassen, wie es die Antwort von @jfs tut.
– Charles Duffy
19. Januar 21 um 1:47 Uhr
jfs
Ich konnte keinen laufenden Prozess sehen.
Sie sehen keinen laufenden Prozess, weil das Kind python Der Prozess wird sofort beendet. Der Popen Argumente sind falsch, wie user4815162342 im Kommentar sagt.
Zum Starten eines völlig unabhängig Prozess, den Sie verwenden könnten python-daemon Paket oder verwenden Sie systemd/supervisord/etc:
#!/usr/bin/python25
import daemon
from long_process import main
with daemon.DaemonContext():
main()
Obwohl es in Ihrem Fall ausreichen könnte, das Kind mit dem Richtigen zu beginnen Popen Argumente:
with open(os.devnull, 'r+b', 0) as DEVNULL:
p = Popen(['/usr/bin/python25', '/path/to/long_process.py'],
stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT, close_fds=True)
time.sleep(1) # give it a second to launch
if p.poll(): # the process already finished and it has nonzero exit code
sys.exit(p.returncode)
Wenn der untergeordnete Prozess dies nicht erfordert python2.5 dann könntest du verwenden sys.executable stattdessen (um dieselbe Python-Version wie die übergeordnete zu verwenden).
Hinweis: Der Code wird geschlossen DEVNULL im Elternprozess, ohne auf das Ende des Kindprozesses zu warten (es hat keine Auswirkung auf das Kind).
.
6024100cookie-checkStarten Sie einen völlig unabhängigen Prozessyes
Können Sie ein Minimalbeispiel posten, das nicht funktioniert? Nach einem trivialen
python -c 'import subprocess; subprocess.Popen(["sleep", "60"])'
die Ausgabe vonps
zeigt, dass diesleep
läuft gut weiter, nachdem Python beendet wurde.– Benutzer4815162342
23. Dezember 2014 um 17:15 Uhr
Sie führen Python mit einem einzigen Argument aus,
"nohup /usr/bin/python25 ..."
, was nicht funktionieren kann, weil diepython
Ausführbare Datei sucht nach einem Skript in einer Datei mit dem genauen Namennohup /usr/bin/...
, die es nicht gibt. Und da Sie angebenstderr
wiePIPE
ohne jemals den Inhalt der Pipe zu lesen, bekommen Sie die Fehlermeldung nie zu sehen. Verliere dienohup
und&
, und einfach laufensubprocess.Popen([sys.executable, "/.../long_process.py"])
. Auch nicht angebenstdin
undstderr
als Rohre, es sei denn, Sie meinen es so.– Benutzer4815162342
23. Dezember 14 um 17:21 Uhr
nohup
am sinnvollsten, wenn Sie einen Prozess von einer Shell aus starten. Ich sehe nichtshell=True
in deinemPopen
Anruf.– 9000
23. Dezember 14 um 17:42 Uhr