Chinaunix首页 | 论坛 | 博客
  • 博客访问: 183767
  • 博文数量: 20
  • 博客积分: 1510
  • 博客等级: 上尉
  • 技术积分: 214
  • 用 户 组: 普通用户
  • 注册时间: 2006-10-11 23:54
个人简介

一个异想天开的coder

文章分类

全部博文(20)

文章存档

2014年(5)

2013年(4)

2012年(2)

2011年(1)

2008年(1)

2007年(6)

2006年(1)

分类: Python/Ruby

2013-12-11 13:13:40

参考:http://www.tsheffler.com/blog/?p=377



点击(此处)折叠或打开

  1. # -*- coding: utf-8 -*-
  2. '''
  3.     This module is used to fork the current process into a daemon.
  4.     Almost none of this is necessary (or advisable) if your daemon
  5.     is being started by inetd. In that case, stdin, stdout and stderr are
  6.     all set up for you to refer to the network connection, and the fork()s
  7.     and session manipulation should not be done (to avoid confusing inetd).
  8.     Only the chdir() and umask() steps remain as useful.
  9.     References:
  10.         UNIX Programming FAQ
  11.             1.7 How do I get my program to act like a daemon?
  12.                 
  13.         Advanced Programming in the Unix Environment
  14.             W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.

  15.     History:
  16.       2001/07/10 by Jürgen Herman
  17.       2002/08/28 by Noah Spurrier
  18.       2003/02/24 by Clark Evans

  19.       
  20. '''
  21. import sys, os, time
  22. from signal import SIGTERM

  23. def deamonize(stdout='/dev/null', stderr=None, stdin='/dev/null',
  24.               pidfile=None, startmsg = 'started with pid %s' ):
  25.     '''
  26.         This forks the current process into a daemon.
  27.         The stdin, stdout, and stderr arguments are file names that
  28.         will be opened and be used to replace the standard file descriptors
  29.         in sys.stdin, sys.stdout, and sys.stderr.
  30.         These arguments are optional and default to /dev/null.
  31.         Note that stderr is opened unbuffered, so
  32.         if it shares a file with stdout then interleaved output
  33.         may not appear in the order that you expect.
  34.     '''
  35.     # Do first fork.
  36.     try:
  37.         pid = os.fork()
  38.         if pid > 0: sys.exit(0) # Exit first parent.
  39.     except OSError, e:
  40.         sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
  41.         sys.exit(1)
  42.     # Decouple from parent environment.
  43.     os.chdir("/")
  44.     os.umask(0)
  45.     os.setsid()

  46.     # Do second fork.
  47.     try:
  48.         pid = os.fork()
  49.         if pid > 0: sys.exit(0) # Exit second parent.
  50.     except OSError, e:
  51.         sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
  52.         sys.exit(1)

  53.     # Open file descriptors and print start message
  54.     if not stderr: stderr = stdout
  55.     si = file(stdin, 'r')
  56.     so = file(stdout, 'a+')
  57.     se = file(stderr, 'a+', 0)
  58.     pid = str(os.getpid())
  59.     sys.stderr.write("\n%s\n" % startmsg % pid)
  60.     sys.stderr.flush()
  61.     if pidfile: file(pidfile,'w+').write("%s\n" % pid)

  62.     # Redirect standard file descriptors.
  63.     os.dup2(si.fileno(), sys.stdin.fileno())
  64.     os.dup2(so.fileno(), sys.stdout.fileno())
  65.     os.dup2(se.fileno(), sys.stderr.fileno())

  66. def startstop(stdout='/dev/null', stderr=None, stdin='/dev/null',
  67.               pidfile='pid.txt', startmsg = 'started with pid %s' ):
  68.     if len(sys.argv) > 1:
  69.         action = sys.argv[1]
  70.         try:
  71.             pf = file(pidfile,'r')
  72.             pid = int(pf.read().strip())
  73.             pf.close()
  74.         except IOError:
  75.             pid = None
  76.         if 'stop' == action or 'restart' == action:
  77.             if not pid:
  78.                 mess = "Could not stop, pid file '%s' missing.\n"
  79.                 sys.stderr.write(mess % pidfile)
  80.                 sys.exit(1)
  81.             try:
  82.                while 1:
  83.                    os.kill(pid,SIGTERM)
  84.                    time.sleep(1)
  85.             except OSError, err:
  86.                err = str(err)
  87.                if err.find("No such process") > 0:
  88.                    os.remove(pidfile)
  89.                    if 'stop' == action:
  90.                        sys.exit(0)
  91.                    action = 'start'
  92.                    pid = None
  93.                else:
  94.                    print str(err)
  95.                    sys.exit(1)
  96.         if 'start' == action:
  97.             if pid:
  98.                 mess = "Start aborded since pid file '%s' exists.\n"
  99.                 sys.stderr.write(mess % pidfile)
  100.                 sys.exit(1)
  101.             deamonize(stdout,stderr,stdin,pidfile,startmsg)
  102.             return
  103.     print "usage: %s start|stop|restart" % sys.argv[0]
  104.     sys.exit(2)

  105. def test():
  106.     '''
  107.         This is an example main function run by the daemon.
  108.         This prints a count and timestamp once per second.
  109.     '''
  110.     sys.stdout.write ('Message to stdout...')
  111.     sys.stderr.write ('Message to stderr...')
  112.     c = 0
  113.     while 1:
  114.         sys.stdout.write ('%d: %s\n' % (c, time.ctime(time.time())) )
  115.         sys.stdout.flush()
  116.         c = c + 1
  117.         time.sleep(1)

  118. if __name__ == "__main__":
  119.     startstop(stdout='/tmp/deamonize.log',
  120.               pidfile='/tmp/deamonize.pid')
  121.     test()

使用的时候:

点击(此处)折叠或打开

  1. SIGTERM_SENT = False

  2. def sigterm_handler(signum, frame):
  3.     print >>sys.stderr, "SIGTERM handler. Shutting Down."

  4.     global SIGTERM_SENT
  5.     if not SIGTERM_SENT:
  6.         SIGTERM_SENT = True
  7.         print >>sys.stderr, "Sending TERM to PG"
  8.         os.killpg(0, signal.SIGTERM)

  9.     sys.exit()

  10. def main():
  11.     # set session ID to this process so we can kill group in sigterm handler
  12.     os.setsid()
  13.     signal.signal(signal.SIGTERM, sigterm_handler)

  14.     while True:
  15.         # ... run daemon threads and subprocesses with impunity.

  16.     # ... this function never returns ...

  17. from daemonize import startstop

  18. if __name__== "__main__":
  19.     startstop(stdout="/var/log/example.log",
  20.               pidfile="/var/run/example.pid")
  21.     main()
main函数中的os.setsid()的作用是将daemon进程设为会话ID。然后退出的时候用os.killpg(0, signal.SIGTERM)将进程组杀掉就可以了。
阅读(1691) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~