Может ли канал подпроцесса python повторно подключиться к исходному дочернему процессу при перезапуске программы?

Я ищу безопасный способ перезапустить мою программу на Python, которая может восстановить контроль над дочерним процессом, запущенным перед перезапуском.

Я использую подпроцесс с потоком для мониторинга stdout/stderr длительного запуска command, который будет постоянно генерировать какое-то выходное сообщение.

Пример фрагмента кода выглядит следующим образом:

class PS(threading.Thread):
    def __init__(self, command):
        threading.Thread.__init__(self)
        self.command = command

    def run(self):
        try:
            process = subprocess.Popen(self.command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            for line in iter(process.stdout.readline, ''):
                ''' do something to line'''

Когда моя основная программа Python завершается (например, убивает ее pid), ее дочерний процесс (command, выполняемый классом PS) все еще жив как фоновый процесс.

Мой вопрос: есть ли способ в python «повторно подключить» дочерний процесс, чтобы я мог продолжать отслеживать его stdout/stderr?

P.S. Мне это нужно только в среде Linux, точнее в Ubuntu 14.04.


person user1817188    schedule 18.08.2014    source источник
comment
Дочерний процесс, вероятно, умрет, если он попытается записать в свой стандартный вывод после выхода родителя, потому что его стандартный вывод был каналом, другой конец которого был родителем, а не файлом.   -  person chepner    schedule 18.08.2014
comment
@chepner Я не знаю как, но я уверен, что дочерний процесс жив.   -  person user1817188    schedule 18.08.2014
comment
Но он все еще производит продукцию? Даже если он каким-то образом буферизован, ваша программа все равно может потерять часть вывода в зависимости от того, сколько времени потребуется для повторного подключения. Просто напишите в файл, и пусть родитель читает из файла, а не из канала.   -  person chepner    schedule 18.08.2014
comment
Я попробовал небольшой пример ("while :; do echo $i; i=$((i+1)); sleep 1; done"), и этот дочерний процесс не пережил завершение родительского процесса Python.   -  person chepner    schedule 18.08.2014
comment
@chepner следующий пример import subprocess; subprocess.Popen(['python', '-c', 'while True: print("test")']) действительно переживает завершение родительского процесса python.   -  person simonzack    schedule 18.08.2014
comment
Без stdout=subprocess.PIPE его стандартный вывод просто наследуется от родителя, а не устанавливается в канал, другая конечная точка которого исчезает при выходе родителя.   -  person chepner    schedule 18.08.2014
comment
Действительно, вы правы, дочерний процесс завершается с конвейером.   -  person simonzack    schedule 18.08.2014
comment
@chepner command, который я запускаю, на самом деле является процессом QEMU, который запускает виртуальную машину. Я заметил, что виртуальная машина жива после завершения кода Python. В любом случае, как вы предложили, просто записать в файл кажется многообещающим решением.   -  person user1817188    schedule 18.08.2014


Ответы (1)


Когда стандартный вывод дочернего элемента привязан к каналу, дочерний элемент получит сигнал SIGPIPE, если он попытается записать в этот канал после смерти родителя, поскольку удаленный конец канала больше не существует.

Чтобы гарантировать, что дочерний процесс переживет родителя, и позволить родителю возобновить работу, вы должны просто записать в файл, а родитель вместо этого будет читать из этого файла.

person chepner    schedule 18.08.2014