У меня есть программа python, которая использует subprocess.Popen
для запуска другого процесса (процесс python или что-то еще), и после его запуска я сохраняю дочерний PID в файл. Предположим, что внезапно родительский процесс умирает (из-за исключения или чего-то еще). Есть ли способ получить доступ к объекту, возвращенному Popen
?
Я имею в виду, что основная идея состоит в том, чтобы сначала прочитать файл, и если он существует, и на нем есть ПИД-код, написанный на нем, то доступ к этому процессу каким-то образом, чтобы узнать код возврата или что-то еще. Если нет PID, запустите процесс с помощью Popen
.
Спасибо большое!
Объект Popen фактически является просто оболочкой для дочерних процессов PID, stdin, stdout и stderr, а также некоторыми удобными функциями для их использования.
Итак, возникает вопрос, почему вам нужен доступ к объекту Popen? Вы хотите установить связь с дочерним узлом, завершить его или проверить, все ли работает?
В любом случае невозможно вернуть объект Popen для уже запущенного процесса.
Правильный способ приблизиться к этому - запустить ребенка как демона, как предложил Тобу. Часть процедуры демонстрации процесса состоит в закрытии stdin и stdout, поэтому вы не можете использовать их для обсуждения с дочерним процессом. Вместо этого большинство демонов используют либо каналы, либо сокеты, чтобы клиенты могли подключаться к ним и отправлять их сообщениям.
Самый простой способ поговорить с ребенком - открыть именованный канал из дочернего процесса, например. /etc/my _pipe, откройте этот именованный канал из родительского/управляющего процесса и напишите/прочитайте в/из него.
После быстрого просмотра python-daemon мне кажется, что python-daemon поможет вам демонировать ваш дочерний процесс, что сложно сделать правильно, но это не поможет вам в обмене информацией.
Но, как я уже сказал, я думаю, вам нужно рассказать нам, почему вам нужен объект Popen для дочернего процесса, прежде чем мы сможем вам помочь.
Если процесс умирает, все его открытые дескрипторы файлов закрыты. Сюда входят любые неназванные каналы, созданные popen()
. Итак, нет, нет способа восстановить объект Popen
только из PID. ОС даже не рассмотрит ваш новый процесс как родительский, поэтому вы даже не получите сигналы SIGCHLD
(хотя waitpid()
может работать).
Я не уверен, что ребенок также будет выживать, поскольку запись в канал без чтения (а именно, перенаправленный stdout
ребенка) должна убить ребенка с помощью SIGPIPE
.
Если вы хотите, чтобы ваш родительский процесс забирал место, где был остановлен ребенок, вам необходимо создать дочерний элемент для записи в файл, обычно в /tmp
или /var/log
, и записать его PID, как сейчас (обычное местоположение /var/run
). (Имейте это, пишите в именованный канал, рискуя убить его с помощью SIGPIPE
, как указано выше.) Если вы суффикс вашего имени файла с помощью PID, тогда процесс менеджера легко определить, какой файл принадлежит демону.
Похоже, вы пытаетесь написать демона, и ему нужна поддержка 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…)