No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

daemon.py 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #!/usr/bin/env python
  2. import sys, os, time, atexit
  3. from signal import SIGTERM
  4. class Daemon:
  5. """
  6. A generic daemon class.
  7. Usage: subclass the Daemon class and override the run() method
  8. """
  9. def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
  10. self.stdin = stdin
  11. self.stdout = stdout
  12. self.stderr = stderr
  13. self.pidfile = pidfile
  14. def daemonize(self):
  15. """
  16. do the UNIX double-fork magic, see Stevens' "Advanced
  17. Programming in the UNIX Environment" for details (ISBN 0201563177)
  18. http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
  19. """
  20. try:
  21. pid = os.fork()
  22. if pid > 0:
  23. # exit first parent
  24. sys.exit(0)
  25. except OSError, e:
  26. sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
  27. sys.exit(1)
  28. # decouple from parent environment
  29. os.chdir("/")
  30. os.setsid()
  31. os.umask(0)
  32. # do second fork
  33. try:
  34. pid = os.fork()
  35. if pid > 0:
  36. # exit from second parent
  37. sys.exit(0)
  38. except OSError, e:
  39. sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
  40. sys.exit(1)
  41. # redirect standard file descriptors
  42. sys.stdout.flush()
  43. sys.stderr.flush()
  44. si = file(self.stdin, 'r')
  45. so = file(self.stdout, 'a+')
  46. se = file(self.stderr, 'a+', 0)
  47. os.dup2(si.fileno(), sys.stdin.fileno())
  48. os.dup2(so.fileno(), sys.stdout.fileno())
  49. os.dup2(se.fileno(), sys.stderr.fileno())
  50. # write pidfile
  51. atexit.register(self.delpid)
  52. pid = str(os.getpid())
  53. file(self.pidfile,'w+').write("%s\n" % pid)
  54. def delpid(self):
  55. os.remove(self.pidfile)
  56. def start(self):
  57. """
  58. Start the daemon
  59. """
  60. # Check for a pidfile to see if the daemon already runs
  61. try:
  62. pf = file(self.pidfile,'r')
  63. pid = int(pf.read().strip())
  64. pf.close()
  65. except IOError:
  66. pid = None
  67. if pid:
  68. message = "pidfile %s already exist. Daemon already running?\n"
  69. sys.stderr.write(message % self.pidfile)
  70. sys.exit(1)
  71. # Start the daemon
  72. self.daemonize()
  73. self.run()
  74. def stop(self):
  75. """
  76. Stop the daemon
  77. """
  78. # Get the pid from the pidfile
  79. try:
  80. pf = file(self.pidfile,'r')
  81. pid = int(pf.read().strip())
  82. pf.close()
  83. except IOError:
  84. pid = None
  85. if not pid:
  86. message = "pidfile %s does not exist. Daemon not running?\n"
  87. sys.stderr.write(message % self.pidfile)
  88. return # not an error in a restart
  89. # Try killing the daemon process
  90. try:
  91. while 1:
  92. os.kill(pid, SIGTERM)
  93. time.sleep(0.1)
  94. except OSError, err:
  95. err = str(err)
  96. if err.find("No such process") > 0:
  97. if os.path.exists(self.pidfile):
  98. os.remove(self.pidfile)
  99. else:
  100. print str(err)
  101. sys.exit(1)
  102. def restart(self):
  103. """
  104. Restart the daemon
  105. """
  106. self.stop()
  107. self.start()
  108. def run(self):
  109. """
  110. You should override this method when you subclass Daemon. It will be called after the process has been
  111. daemonized by start() or restart().
  112. """