2016-05-05 38 views
4

Mein Ziel ist einfach: Kick Rsync und nicht warten.Hintergrundprozess in Python ausführen und nicht warten

Python 2.7.9 auf Debian

Beispielcode:

rsync_cmd = "/usr/bin/rsync -a -e 'ssh -i /home/myuser/.ssh/id_rsa' {0}@{1}:'{2}' {3}".format(remote_user, remote_server, file1, file1) 
rsync_cmd2 = "/usr/bin/rsync -a -e 'ssh -i /home/myuser/.ssh/id_rsa' {0}@{1}:'{2}' {3} &".format(remote_user, remote_server, file1, file1) 
rsync_path = "/usr/bin/rsync" 
rsync_args = shlex.split("-a -e 'ssh -i /home/mysuser/.ssh/id_rsa' {0}@{1}:'{2}' {3}".format(remote_user, remote_server, file1, file1)) 
#subprocess.call(rsync_cmd, shell=True)  # This isn't supposed to work but I tried it 
#subprocess.Popen(rsync_cmd, shell=True) # This is supposed to be the solution but not for me 
#subprocess.Popen(rsync_cmd2, shell=True) # Adding my own shell "&" to background it, still fails 
#subprocess.Popen(rsync_cmd, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) # This doesn't work 
#subprocess.Popen(shlex.split(rsync_cmd)) # This doesn't work 
#os.execv(rsync_path, rsync_args)   # This doesn't work 
#os.spawnv(os.P_NOWAIT, rsync_path, rsync_args) # This doesn't work 
#os.system(rsync_cmd2)      # This doesn't work 
print "DONE" 

(Ich habe nur die Ausführungsbefehle kommentiert, weil ich eigentlich bin alle meine Versuche in meinem Code zu halten, so dass ich Ich weiß, was ich getan habe und was ich nicht getan habe. Offensichtlich würde ich das Skript mit der richtigen Zeile unkommentiert ausführen.)

Was passiert ist das ... Ich kann die Übertragung auf dem Server und wann es ist fertig, dann bekomme ich eine "FERTIG" auf den Bildschirm gedruckt.

Was ich möchte passieren, ist eine "DONE" gedruckt unmittelbar nach der Ausgabe der rsync Befehl und für den Transfer zu starten.

Scheint sehr geradlinig. Ich habe ALLE Vorschläge der Interwebs ausprobiert und ich habe NICHTS gefunden, das für mich funktioniert.

Vielen Dank für die Zeit.

(Ich bin sicher, jeder wird "Dies ist ein Duplikat" anbieten, aber jeder Eintrag, den ich in der gesamten StackExchange-Community gefunden habe, scheitert. Wenn du einen hast, den ich ausprobieren soll, gib ihn bitte weiter . entlang, bevor Sie denken, dies ist ein Duplikat)

+1

Scheint die Frage beantwortet wird [hier] (http://stackoverflow.com/a/2251026/3070670) –

+0

@ viach Zeiger ist Ihre beste Wette. – WreckeR

+0

[Dieser] (http://stackoverflow.com/questions/3516007/run-process-and-dont-wait#comment19551411_6700359) sagt "creationflags" ist nur Windows. Der Link, den Sie angegeben haben, spricht auch über Win32. – harperville

Antwort

8

Hier ist Beispiel für Python REPL verifiziert:

>>> import subprocess 
>>> import sys 
>>> p = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(100)'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT); print('finished') 
finished 

Wie das über ein anderes Terminal-Fenster überprüfen:

$ ps aux | grep python 

Ausgang:

user   32820 0.0 0.0 2447684 3972 s003 S+ 10:11PM 0:00.01 /Users/user/venv/bin/python -c import time; time.sleep(100) 
+0

Das funktioniert bei mir auch im Interpreter, aber nicht in meinem Skript. Ich muss anfangen, es zu nichts herunterzureißen und es wieder aufzubauen. Ich werde auch 'Process()' versuchen, wie von @asav oben empfohlen. – harperville

+0

Ich habe nach dem Aufrufen von Popen eine Nachricht in das Protokoll gedruckt, wie in Ihrem Beispiel gezeigt, und ich sah meine Nachricht im Protokoll. Das Problem ist woanders, dass ich noch finden muss, aber wie üblich, half mir dein Vorschlag, festzustellen, dass Popen nicht das Problem war. Danke für die Hilfe! Ich verwende 'p = subprocess (rsync_dict, close_fds = True)' ist es funktioniert wie angekündigt. – harperville

+1

@harperville Ich fühle mich wie der Grund für das Verhalten in Ihrem Befehl ist, der wahrscheinlich auf einige Eingaben von 'stdin' wartet. –

2

Popen() beginnt ein Kind prozess es wartet nicht, es zu verlassen. Sie müssen die Methode .wait() explizit aufrufen, wenn Sie auf den untergeordneten Prozess warten möchten. In diesem Sinne sind alle Teilprozesse Hintergrundprozesse.

Auf der anderen Seite kann der untergeordnete Prozess verschiedene Eigenschaften/Ressourcen vom übergeordneten Element wie offene Dateideskriptoren, die Prozessgruppe, das Steuerterminal, einige Signalkonfigurationen usw. erben - dies kann dazu führen, dass Ahnenprozesse nicht beendet werden zB Python subprocess .check_call vs .check_output oder das Kind kann vorzeitig mit Strg-C sterben (SIGINT-Signal wird an die Vordergrund-Prozessgruppe gesendet) oder wenn die Terminalsitzung geschlossen ist (SIGHUP).

Um den untergeordneten Prozess vollständig zu trennen, sollten Sie eine daemon machen. Manchmal kann etwas dazwischen ausreichend sein, z. B. reicht es bis redirect the inherited stdout in a grandchild so that .communicate() in the parent would return when its immediate child exits.

Verwandte Themen