Понимание кода Python для создания процесса демона

(Я понимаю, что есть некоторые существующие вопросы по SO по той же теме, и я прочитал самые популярные ответы. Эти ответы хороши, но у меня все еще есть что-то неясное.) Недавно я наткнулся на кусок Python для создания процесса демона в системе Unix: образец кода И часть, о которой я хочу поговорить:

def daemonize(self):
    """
    do the UNIX double-fork magic, see Stevens' "Advanced
    Programming in the UNIX Environment" for details (ISBN 0201563177)
    http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
    """
    try:
            pid = os.fork()
            if pid > 0:
                    # exit first parent
                    sys.exit(0)
    except OSError, e:
            sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
            sys.exit(1)

    # decouple from parent environment
    os.chdir("/")
    os.setsid()
    os.umask(0)

    # do second fork
    try:
            pid = os.fork()
            if pid > 0:
                    # exit from second parent
                    sys.exit(0)
    except OSError, e:
            sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
            sys.exit(1)

    # redirect standard file descriptors
    sys.stdout.flush()
    sys.stderr.flush()
    si = file(self.stdin, 'r')
    so = file(self.stdout, 'a+')
    se = file(self.stderr, 'a+', 0)
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

    # write pidfile
    atexit.register(self.delpid)
    pid = str(os.getpid())
    file(self.pidfile,'w+').write("%s\n" % pid)

Итак, процесс такой:

  1. Создать вилку текущего процесса и убить родительский процесс. Итак, в этом случае разветвленный процесс 1 теперь является сиротой.
  2. отделить от родительской среды - зачем мы это делаем? означает ли это, что, задав sid разветвленного процесса 1, мы можем изолировать разветвленный процесс? на этом этапе разветвленный процесс 1 имеет свою собственную группу процессов и сеанс (равный его pid), что означает, что он является лидером сеанса, что означает возможность получения нового управляющего терминала.
  3. снова форкнуть и убить разветвленный процесс 1. Разветвленный процесс 2 теперь тоже сирота. и это определенно не лидер сеанса (был разветвленный процесс 1). и он ничего не разделяет с исходной средой родительского процесса.
  4. выполнить перенаправление ввода / вывода / ошибки.

Итак, правильно ли я понимаю процесс создания процесса-демона? Также некоторые люди упомянули, что «это может предотвратить процессы зомби» в ИТОГО вопрос, почему этот фрагмент кода вообще связан с процессом зомби? Родитель будет убит, чтобы процесс контролировался init, не что означает "демон"?

Некоторые люди также упоминают, что однократное разветвление уже должно дать нам хороший процесс демона. Любой пример для этого? Любой пример (система), при котором вилка однажды может не работать просто как хороший демон?


person Junchao Gu    schedule 29.02.2016    source источник
comment
Возможный дубликат Что такое зачем выполнять двойную вилку при создании демона?   -  person Zaur Nasibov    schedule 29.02.2016
comment
Я упомянул этот вопрос в своем вопросе и прочитал 3 основных ответа на этот вопрос. Это хорошие ответы, но у меня все еще есть что-то неясное, что уже включено в мой вопрос   -  person Junchao Gu    schedule 29.02.2016
comment
Некоторые ответы в связанном вопросе также объясняют, что двойное разветвление требуется только в том случае, если ожидается, что родительский процесс будет жить дольше, чем дочерний (таким образом, дочерний процесс останется зомби в таблице родительских процессов).   -  person Dunes    schedule 29.02.2016


Ответы (1)


Процесс, являющийся частью того же сеанса, означает, что когда bash получает сигнал SIGHUP при отключении по ssh, он завершает все процессы в сеансе. Обработчик SIGHUP по умолчанию также завершает процесс. Чтобы избежать этого, вы хотите создать новый сеанс.

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


Итак ... вы не хотите быть участником сеанса TTY и не хотите быть лидером сеанса, потому что они получают сигнал.

Вот почему вы запускаете демон: вы запускаете python1, этот процесс разветвляется, вы получаете python1 и python2. Python2 начинает новый сеанс и разветвляется, поэтому вы получаете python3.

Setid в python2 гарантирует, что python3 не подключен к сеансу python1, а вилка в python2 необходима, потому что python2 по-прежнему является лидером сеанса.

Тогда Python3 не будет получать никаких сигналов, связанных с TTY, и не будет отключен SIGHUP при отключении или любых других событиях, связанных с TTY, на коробке.

person hruske    schedule 29.02.2016