2016-05-05 2 views
4

Моя цель проста: отпустите rsync и НЕ ЖДИТЕ.Запустите фоновый процесс в Python и не ждите

Python 2.7.9 на Debian

Пример кода:

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 и для начала передачи.

Кажется, очень прямолинейно. Я пробовал ВСЕ предложения, предлагаемые Interwebs, и я нашел НИЧЕГО, что работает для меня.

Спасибо заранее.

(Я уверен, что все будут предлагать «Это дубликат», но каждая запись, которую я обнаружил во всем сообществе StackExchange, терпит неудачу. Если у вас есть тот, который вы хотите, чтобы я попытался передать его . вместе, прежде чем вы думаете, что это дубликат)

+1

Похоже, на вопрос отвечает [здесь] (http://stackoverflow.com/a/2251026/3070670) –

+0

Указатель bych - ваш лучший выбор. – WreckeR

+0

[This one] (http://stackoverflow.com/questions/3516007/run-process-and-dont-wait#comment19551411_6700359) говорит, что «creationflags» - только для Windows. Вы также указали ссылку на Win32. – harperville

ответ

8

Здесь проверяется пример для Python РЕПЛ:

>>> 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) 
+0

Это работает и для меня в интерпретаторе, но не для моего сценария. Я должен начать срывать его до нуля и строить его обратно. Я также попробую 'Process()' как рекомендовано @asav выше. – harperville

+0

Я напечатал сообщение в журнал после вызова Popen, как показывает ваш пример, и я увидел свое сообщение в журнале. Проблема в другом месте, которую я еще не нашел, но, как обычно, ваше предложение помогло мне определить, что Popen не проблема. Спасибо за помощь! Я использую 'p = subprocess (rsync_dict, close_fds = True)' работает, как рекламируется. – harperville

+1

@harperville Я чувствую, что причина вашего поведения в вашей команде, которая, вероятно, ждет ввода от 'stdin'. –

2

Popen() начинается процесс-то ребенок не ждать его, чтобы выйти. Вы должны вызвать метод .wait() явно, если вы хотите дождаться дочернего процесса. В этом смысле все подпроцессы являются фоновыми процессами.

С другой стороны, дочерний процесс может наследовать различные свойства/ресурсы от родителя, такие как дескрипторы открытых файлов, группа процессов, его управляющий терминал, некоторая конфигурация сигнала и т. Д. Это может привести к тому, что процессы предшественников не будут завершены например, Python subprocess .check_call vs .check_output, или ребенок может умереть преждевременно на Ctrl-C (сигнал SIGINT отправляется в группу процессов переднего плана), или если сеанс терминала закрыт (SIGHUP).

Чтобы полностью отключить дочерний процесс, вы должны сделать это daemon. Иногда что-то между ними может быть достаточно, например, достаточно до redirect the inherited stdout in a grandchild so that .communicate() in the parent would return when its immediate child exits.