Восстановить процесс с помощью подпроцесса. Открыть? - PullRequest
1 голос
/ 13 января 2010

У меня есть программа на Python, которая использует subprocess.Popen для запуска другого процесса (процесс Python или любой другой), и после запуска я сохраняю PID ребенка в файл. Давайте предположим, что внезапно родительский процесс умирает (из-за исключения или чего-то еще). Есть ли способ снова получить доступ к объекту, возвращенному Popen?

Я имею в виду, основная идея - сначала прочитать файл, и если он существует и на нем написан PID, то каким-то образом получить доступ к этому процессу, чтобы узнать код возврата или что-то еще. Если PID отсутствует, запустите процесс с Popen.

Большое спасибо !!

Ответы [ 3 ]

2 голосов
/ 13 января 2010

Объект Popen - это просто оболочка для дочерних процессов PID, stdin, stdout и stderr, а также некоторые удобные функции для их использования.

Итак, вопрос в том, зачем вам нужен доступ к объекту Popen? Хотите ли вы общаться с ребенком, прервать его или проверить, работает ли он еще?

В любом случае невозможно повторно получить объект Popen для уже запущенного процесса.

Правильный способ подойти к этому - запустить ребенка в качестве демона, как предложил Тобу. Частью процедуры демонизации процесса является закрытие stdin и stdout, поэтому вы не можете использовать их для общения с дочерним процессом. Вместо этого большинство демонов используют либо каналы, либо сокеты, чтобы позволить клиентам подключаться к ним и отправлять им сообщения.

Самый простой способ поговорить с дочерним элементом - открыть именованный канал из дочернего процесса, например, по адресу. / etc / my_pipe, откройте этот именованный канал из родительского / управляющего процесса и запишите / прочитайте / из него.

После быстрого взгляда на python-daemon мне кажется, что python-daemon поможет вам демонизировать ваш дочерний процесс, что сложно сделать правильно, но это не поможет вам в части обмена сообщениями. *

Но, как я уже сказал, я думаю, что вы должны сказать нам, почему вам нужен объект Popen для дочернего процесса, прежде чем мы сможем помочь вам в дальнейшем.

1 голос
/ 13 января 2010

Если процесс умирает, все его дескрипторы открытых файлов закрываются. Это включает в себя любые безымянные каналы, созданные popen(). Так что нет, нет способа восстановить Popen объект только из PID. ОС даже не будет рассматривать ваш новый процесс как родительский, поэтому вы даже не получите SIGCHLD сигналов (хотя waitpid() все еще может работать).

Я не уверен, что ребенок гарантированно выживет, поскольку запись в канал без читателя (а именно, перенаправленный stdout ребенка) должна убить ребенка с SIGPIPE.

Если вы хотите, чтобы ваш родительский процесс продолжал с того места, где остановился дочерний процесс, вам нужно порождать дочернего процесса для записи в файл, обычно в /tmp или /var/log, и заставить его записывать свой PID, как вы сейчас (обычное местоположение /var/run). (При записи в именованный канал рискует быть уничтоженным с помощью SIGPIPE, как указано выше.) Если вы суффиксите свое имя файла с PID, тогда процессу менеджера будет легко выяснить, какой файл принадлежит какому-либо демону.

0 голосов
/ 13 января 2010

Похоже, вы пытаетесь написать демон, и ему нужна поддержка pidfile. Вы не ошибетесь с python-daemon .

Например:

import daemon
import lockfile
import os

with daemon.DaemonContext(pidfile=lockfile.FileLock('/var/run/spam.pid')):
    os.execl('/path/to/prog', args…)
...