web-dev-qa-db-ja.com

バックグラウンドプロセスをPythonで実行し、待機しないでください

私の目標は単純です:rsyncを開始し、待機しないでください。

Debian上のPython 2.7.9

サンプルコード:

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"

(実行コマンドをコメントアウトしているのは、実際にすべての試行をコードに保持しているため、実行したことと実行していないことを把握できるためです。明らかに、スクリプトを適切に実行します行のコメントを外します。)

これが起こるのは...サーバー上で転送を見ることができ、それが完了すると、画面に「DONE」と表示されます。

したいのは、rsyncコマンドを発行した直後に転送を開始するための「完了」です。

非常に簡単なようです。 this oneや this oneなど、他の投稿で説明されている詳細に従いましたが、何らかの理由で機能していません。

事前に感謝します。

(StackExchangeで見つけることができるすべてを試しましたが、まだ動作させることができないため、これが重複しているとは感じません。セットアップで何かが正しくなく、助けが必要です。)

9
harperville

Python REPL:

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

別の端末ウィンドウを介してそれを確認する方法:

$ ps aux | grep python

出力:

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)
16
Viach Kakovskyi

Popen()は子プロセスを開始します。子プロセスが終了するまで待機しません。子プロセスを待つ場合は、.wait()メソッドを明示的に呼び出す必要があります。その意味で、すべてのサブプロセスはバックグラウンドプロセスです。

一方、子プロセスは、開いているファイル記述子、プロセスグループ、その制御端末、一部の信号構成など、親からさまざまなプロパティ/リソースを継承する可能性があります。 Pythonサブプロセス.check_call vs .check_output または、Ctrl-C(SIGINTシグナルがフォアグラウンドプロセスグループに送信される)またはターミナルセッションが閉じられる(SIGHUP)場合、子が早期に死ぬことがあります。

子プロセスを完全に分離するには、それを daemon にする必要があります。間にあるもので十分な場合もあります。たとえば、 親の.communicate()が直接の子が終了したときに戻るように、孫の継承されたstdoutをリダイレクトします で十分です。

8
jfs