首页 文章

了解用于创建守护程序进程的Python代码

提问于
浏览
1

(我知道有关于同一主题的SO有一些现有问题,我已经阅读了最佳答案 . 这些答案很好,但我还有一些不清楚的地方 . )最近我遇到了一段用于在Unix系统中创建守护进程的Python:sample code我要谈的那篇文章:

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)

所以这个过程是:

  • 创建当前进程的fork并终止父进程 . 所以在这种情况下,分叉进程1现在是一个孤儿 .

  • 与父环境分离 - why do we do this? 这是否意味着通过设置分叉进程1的sid,我们可以隔离分叉进程?此时,分叉进程1有自己的进程组和会话(等于其pid),这意味着它是一个会话负责人,这意味着可以获得一个新的控制终端 .

  • 再次fork和kill forked进程1.分叉进程2现在也是一个孤儿 . 它绝对不是会话领导者(分叉进程1) . 并且它不与原始父进程环境共享任何内容 .

  • 执行输入/输出/错误重定向 .

那么我的理解是否正确创建守护进程的过程?也有人在SO question中提到了"this can prevent zombie processes", why is this piece of code even related to zombie process? 将会杀死父进程,以便init监视进程, is not that what "daemon" means?

Some people also mention that forking once should give us a good daemon process already. Any example for this? Any example(system) under which fork once may not just work as a good daemon?

1 回答

  • 2

    作为同一会话一部分的进程意味着当您通过ssh断开连接时bash收到SIGHUP,它会终止会话中的所有进程 . 默认的SIGHUP处理程序也会终止进程 . 要避免这种情况,您需要创建一个新会话 .

    此外,TTY是一个有点古老的概念,多年来它已经获得了巨大的历史和大量用于交互的角落案例,但在运行守护进程时会产生反作用,因为你不希望内核向你的非守护进程发送随机信号交互式守护程序进程发生TTY相关的事情 .


    所以...你不想成为TTY Session 的成员而你不想成为 Session 领导者,因为那些得到了信号 .

    这就是你启动一个守护进程的原因:你运行python1,这个进程分叉,你得到python1和python2 . Python2启动新的会话和分叉,所以你得到python3 .

    python2中的setsid确保python3没有连接到python1会话,并且需要python2中的fork,因为python2仍然是会话领导者 .

    Python3将不会收到任何与TTY相关的信号,当你断开连接或盒子上发生任何与TTY相关的事情时,它们不会被SIGHUP杀死 .

相关问题