python使用eventlet(协程)启动多个daemon process(守护进程)

这里我们需要解决的问题是:我们有多个服务,且每个服务(server)都是守护进程(daemon process),我们希望一次启动我们所有的服务,即使用eventlet创建我们的daemon processes

1.首先创建我们的守护进程

先创建我们的守护进程类,通过fork()函数实现.
* 关于我们为啥要使用signal.signal(signal.SIGCHLD,signal.SIG_IGN),请参考:
http://blog.csdn.net/u010571844/article/details/50419798.
* 第一次fork()后父进程使用的是sys.exit(0),会产生SystemExit的异常,我们不希望父进程退出,因为我们还希望使用父进程创建其他守护进程,我们可以catch Systemxit 这个异常。
* 第二次fork()后我们使用的是os._exit(0),父进程直接退出。这里为了避免父进程产生僵尸进程,使用了signal.signal(signal.SIGCHLD,signal.SIG_IGN)函数,使父进程的父进程不在关心他的子进程,子进程结束,由系统内核回收。僵尸进程参考:http://blog.csdn.net/u010571844/article/details/50419518
* sys.exit(0)与os._exit(0) 参考:http://blog.csdn.net/u010571844/article/details/50419261

# daemon.py
import sys
import time
import  os
import atexit
import signal
import logging

log = logging.getLogger(__name__)

class Daemon:
    """
        A generic daemon class.
        Usage: subclass the Daemon class and override the run() method
    """
    startmsg = "RPC server started with pid %s"
    """
       A generic daemon class.

       Usage: subclass the Daemon class and override the run() method
       """

    def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr
        self.pidfile = pidfile
        log.info("create daemon pidfile at:%s" % self.pidfile)

    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
        """
    #避免产生僵尸进程
        signal.signal(signal.SIGCHLD,signal.SIG_IGN)
        try:
            pid = os.fork()
            if pid > 0:
                # exit first parent
                log.info("1. fork 1# ----  ppid:%s" % str(os.getpid()))
                sys.exit(0) #该退出方式会产生SystemExit异常,可以捕获,做一些情场工作,不捕获该进程将会退出
        except OSError, e:
            log.error("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
            sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
            sys.exit(1)

        # decouple from parent environment
        log.info("2. fork 1# ----   pid:%s" % str(os.getpid()))
        os.chdir("/")
        os.setsid()
        os.umask(0)

        # do second fork
        try:
            pid = os.fork()
            if pid > 0:
                log.info("3. fork 2# ----   ppid:%s" % str(os.getpid()))
                os._exit(0) #直接退出进程,不会抛异常
        except OSError, e:
            log.error("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
            sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
            sys.exit(1)

        #redirect standard file descriptors
        log.info("4. fork 2# ----   pid:%s" % str(os.getpid()))
        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())
        log.info("write pid : %s to pidfile : %s" %(pid, self.pidfile))
        file(self.pidfile, 'w+').write(
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值