Python порождает дочерний подпроцесс, отсоединяется и выходит - PullRequest
25 голосов
/ 24 апреля 2011

Мне интересно, является ли это правильным способом выполнения системного процесса и отсоединения от родителя, хотя он позволяет родителю выходить без создания зомби и / или уничтожения дочернего процесса.В настоящее время я использую модуль подпроцесса и делаю это ...

os.setsid() 
os.umask(0) 
p = subprocess.Popen(['nc', '-l', '8888'],
                     cwd=self.home,
                     stdout=subprocess.PIPE, 
                     stderr=subprocess.STDOUT)

os.setsid () изменяет группу процессов, что, как я считаю, позволяет продолжить процесс, когда родительский процесс завершается, так какбольше не принадлежит к той же группе процессов.

Правильно ли это, а также является ли это надежным способом выполнения этого?

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

Я читал о двойных вилках и не уверен, если это необходимо, и / или подпроцесс.close_fds как-то заботится об этом, и все, что нужно, это изменить группу процессов?

Спасибо.

Илья

1 Ответ

9 голосов
/ 03 января 2017

popen в Unix сделано с помощью fork. Это означает, что вы будете в безопасности с:

  1. вы запускаете Popen в родительском процессе
  2. немедленно выйти из родительского процесса

При выходе из родительского процесса дочерний процесс наследуется процессом init (launchd в OSX) и будет по-прежнему выполняться в фоновом режиме.

Первые две строки вашей программы на Python не нужны, это прекрасно работает:

import os, time
import subprocess
p = subprocess.Popen(['nc', '-l', '8888'],
                     cwd="/",
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)

Я читал о двойных вилках и не уверен, если это необходимо

Это понадобится, если ваш родительский процесс продолжает работать и вам нужно защитить своих детей от смерти с родителем. Этот ответ показывает, как это можно сделать.

Как работает двойная вилка:

  1. создать ребенка через os.fork()
  2. в этом дочернем вызове Popen(), который запускает длительный процесс
  3. exit child: Popen процесс наследуется init и выполняется в фоновом режиме

Почему родитель должен немедленно выйти? Что произойдет, если он не выйдет сразу?

Если вы оставляете родителя работающим, а пользователь останавливает процесс, например, через ctrl-C (SIGINT) или ctrl-\ (SIGQUIT), тогда он уничтожит как родительский процесс, так и процесс Popen.

Что если он выйдет через одну секунду после разветвления?

Затем, в течение этого периода 1 с, ваш Popen процесс уязвим для ctrl-c и т. Д. Если вам нужно быть на 100% уверенным, используйте двойное разветвление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...