daemon.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #!/usr/bin/env python
  2. import sys
  3. import os
  4. from signal import SIGTERM
  5. class Daemon(object):
  6. """
  7. A generic daemon class.
  8. Usage: subclass the Daemon class and override the run() method
  9. """
  10. def __init__(self, name, pidfile, stdin='/dev/null', stdout='/dev/null',
  11. stderr='/dev/null', noisy=False):
  12. """
  13. initialize some properties needed later.
  14. """
  15. self.stdin = stdin
  16. self.stdout = stdout
  17. self.stderr = stderr
  18. self.pidfile = pidfile
  19. self.name = name
  20. self.noisy = noisy
  21. def daemonize(self):
  22. """
  23. do the UNIX double-fork magic, see Stevens' "Advanced
  24. Programming in the UNIX Environment" for details (ISBN 0201563177)
  25. http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
  26. """
  27. try:
  28. pid = os.fork()
  29. if pid > 0:
  30. # exit first parent
  31. sys.exit(0)
  32. except OSError, e:
  33. sys.stderr.write("fork #1 failed: %d (%s)\n" %
  34. (e.errno, e.strerror))
  35. print("SSSSSDDD")
  36. sys.exit(1)
  37. # decouple from parent environment
  38. os.chdir("/")
  39. os.setsid()
  40. os.umask(0)
  41. # do second fork
  42. try:
  43. pid = os.fork()
  44. if pid > 0:
  45. # exit from second parent
  46. sys.exit(0)
  47. except OSError, e:
  48. sys.stderr.write("fork #2 failed: %d (%s)\n" %
  49. (e.errno, e.strerror))
  50. sys.exit(1)
  51. pid = str(os.getpid())
  52. print("[%s pid: %s]" % (self.name, pid))
  53. # redirect standard file descriptors
  54. sys.stdout.flush()
  55. sys.stderr.flush()
  56. si = open(self.stdin, 'r')
  57. so = open(self.stdout, 'a+')
  58. se = open(self.stderr, 'a+', 0)
  59. if not self.noisy:
  60. os.dup2(si.fileno(), sys.stdin.fileno())
  61. os.dup2(so.fileno(), sys.stdout.fileno())
  62. os.dup2(se.fileno(), sys.stderr.fileno())
  63. open(self.pidfile, 'w+').write("%s\n" % (pid))
  64. def start(self):
  65. """
  66. Start the daemon
  67. """
  68. # Check for a pidfile to see if the daemon already runs
  69. try:
  70. pf = open(self.pidfile, 'r')
  71. pid = int(pf.read().strip())
  72. pf.close()
  73. except IOError:
  74. pid = None
  75. if pid:
  76. message = "pidfile %s already exist. Daemon already running?\n"
  77. sys.stderr.write(message % self.pidfile)
  78. sys.exit(1)
  79. # Start the daemon
  80. self.daemonize()
  81. self.run()
  82. def stop(self):
  83. """
  84. Stop the daemon
  85. """
  86. # Get the pid from the pidfile
  87. try:
  88. pf = open(self.pidfile, 'r')
  89. pid = int(pf.read().strip())
  90. pf.close()
  91. os.remove(self.pidfile)
  92. except IOError:
  93. pid = None
  94. if not pid:
  95. message = "pidfile %s does not exist. Daemon not running?\n"
  96. sys.stderr.write(message % self.pidfile)
  97. return # not an error in a restart
  98. # Try killing the daemon process
  99. try:
  100. os.kill(pid, SIGTERM)
  101. except OSError, err:
  102. err = str(err)
  103. print err
  104. sys.exit(1)
  105. def check_proc(self):
  106. """
  107. check for pid file
  108. """
  109. # Check for a pidfile to see if the daemon already runs
  110. # instead opening self pidfile many times, we should just
  111. # set self.controlpid
  112. try:
  113. pf = open(self.pidfile, 'r')
  114. proc = pf.read()
  115. pid = int(proc.strip())
  116. pf.close()
  117. return pid
  118. except IOError:
  119. message = "pidfile %s does not exist. Daemon not running?\n"
  120. sys.stderr.write(message % self.pidfile)
  121. def restart(self):
  122. """
  123. Restart the daemon
  124. """
  125. self.stop()
  126. self.start()
  127. def exit_running(self):
  128. """
  129. do not start if already running
  130. """
  131. if os.path.exists(self.pidfile):
  132. pf = open(self.pidfile, 'r')
  133. proc = pf.read()
  134. running = int(proc.strip())
  135. message = "pidfile %s already exists. Daemon already running?\n"
  136. message += "check if process %d still exists\n"
  137. sys.stderr.write(message % (self.pidfile, running))
  138. sys.exit(1)
  139. def startd(self):
  140. raise Exception("You should override this method!")
  141. def run(self):
  142. """
  143. You should override this method when you subclass Daemon. It will
  144. be called after the process has been
  145. daemonized by start() or restart().
  146. """
  147. raise Exception("You should override this method!")