Advertisement
Guest User

daemon

a guest
Jul 4th, 2015
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.74 KB | None | 0 0
  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. """
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement