Python daemon example

本文介绍了一个通用的Python守护进程类,通过双fork机制实现后台运行,并详细解释了如何使用该类来启动、停止和重启守护进程。此外,还提供了如何处理标准文件描述符和PID文件的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. #!/usr/bin/env python

  2.  

  3. import sys, os, time, atexit

  4. from signal import SIGTERM

  5.  

  6. class Daemon:

  7.         """

  8.         A generic daemon class.

  9.        

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

  11.         """

  12.         def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):

  13.                 self.stdin = stdin

  14.                 self.stdout = stdout

  15.                 self.stderr = stderr

  16.                 self.pidfile = pidfile

  17.        

  18.         def daemonize(self):

  19.                 """

  20.                 do the UNIX double-fork magic, see Stevens' "Advanced

  21.                 Programming in the UNIX Environment" for details (ISBN 0201563177)

  22.                 http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16

  23.                 """

  24.                 try:

  25.                         pid = os.fork()

  26.                         if pid > 0:

  27.                                 # exit first parent

  28.                                 sys.exit(0)

  29.                 except OSError, e:

  30.                         sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))

  31.                         sys.exit(1)

  32.        

  33.                 # decouple from parent environment

  34.                 os.chdir("/")

  35.                 os.setsid()

  36.                 os.umask(0)

  37.        

  38.                 # do second fork

  39.                 try:

  40.                         pid = os.fork()

  41.                         if pid > 0:

  42.                                 # exit from second parent

  43.                                 sys.exit(0)

  44.                 except OSError, e:

  45.                         sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))

  46.                         sys.exit(1)

  47.        

  48.                 # redirect standard file descriptors

  49.                 sys.stdout.flush()

  50.                 sys.stderr.flush()

  51.                 si = file(self.stdin, 'r')

  52.                 so = file(self.stdout, 'a+')

  53.                 se = file(self.stderr, 'a+', 0)

  54.                 os.dup2(si.fileno(), sys.stdin.fileno())

  55.                 os.dup2(so.fileno(), sys.stdout.fileno())

  56.                 os.dup2(se.fileno(), sys.stderr.fileno())

  57.        

  58.                 # write pidfile

  59.                 atexit.register(self.delpid)

  60.                 pid = str(os.getpid())

  61.                 file(self.pidfile,'w+').write("%s\n" % pid)

  62.        

  63.         def delpid(self):

  64.                 os.remove(self.pidfile)

  65.  

  66.         def start(self):

  67.                 """

  68.                 Start the daemon

  69.                 """

  70.                 # Check for a pidfile to see if the daemon already runs

  71.                 try:

  72.                         pf = file(self.pidfile,'r')

  73.                         pid = int(pf.read().strip())

  74.                         pf.close()

  75.                 except IOError:

  76.                         pid = None

  77.        

  78.                 if pid:

  79.                         message = "pidfile %s already exist. Daemon already running?\n"

  80.                         sys.stderr.write(message % self.pidfile)

  81.                         sys.exit(1)

  82.                

  83.                 # Start the daemon

  84.                 self.daemonize()

  85.                 self.run()

  86.  

  87.         def stop(self):

  88.                 """

  89.                 Stop the daemon

  90.                 """

  91.                 # Get the pid from the pidfile

  92.                 try:

  93.                         pf = file(self.pidfile,'r')

  94.                         pid = int(pf.read().strip())

  95.                         pf.close()

  96.                 except IOError:

  97.                         pid = None

  98.        

  99.                 if not pid:

  100.                         message = "pidfile %s does not exist. Daemon not running?\n"

  101.                         sys.stderr.write(message % self.pidfile)

  102.                         return # not an error in a restart

  103.  

  104.                 # Try killing the daemon process       

  105.                 try:

  106.                         while 1:

  107.                                 os.kill(pid, SIGTERM)

  108.                                 time.sleep(0.1)

  109.                 except OSError, err:

  110.                         err = str(err)

  111.                         if err.find("No such process") > 0:

  112.                                 if os.path.exists(self.pidfile):

  113.                                         os.remove(self.pidfile)

  114.                         else:

  115.                                 print str(err)

  116.                                 sys.exit(1)

  117.  

  118.         def restart(self):

  119.                 """

  120.                 Restart the daemon

  121.                 """

  122.                 self.stop()

  123.                 self.start()

  124.  

  125.         def run(self):

  126.                 """

  127.                 You should override this method when you subclass Daemon. It will be called after the process has been

  128.                 daemonized by start() or restart().

  129.                 """

转载于:https://my.oschina.net/shannanzi/blog/1476844

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值