daemon.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import sys
  4. import time
  5. import atexit
  6. import signal
  7. class Daemon(object):
  8. def __init__(self, pidfile='/tmp/daemon.pid', stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
  9. self.stdin = stdin
  10. self.stdout = stdout
  11. self.stderr = stderr
  12. self.pidfile = pidfile
  13. def daemonize(self):
  14. if os.path.exists(self.pidfile):
  15. raise RuntimeError('Already running.')
  16. # First fork (detaches from parent)
  17. try:
  18. if os.fork() > 0:
  19. raise SystemExit(0)
  20. except OSError as e:
  21. raise RuntimeError('fork #1 faild: {0} ({1})\n'.format(e.errno, e.strerror))
  22. os.chdir('/')
  23. os.setsid()
  24. os.umask(0o22)
  25. # Second fork (relinquish session leadership)
  26. try:
  27. if os.fork() > 0:
  28. raise SystemExit(0)
  29. except OSError as e:
  30. raise RuntimeError('fork #2 faild: {0} ({1})\n'.format(e.errno, e.strerror))
  31. # Flush I/O buffers
  32. sys.stdout.flush()
  33. sys.stderr.flush()
  34. # Replace file descriptors for stdin, stdout, and stderr
  35. with open(self.stdin, 'rb', 0) as f:
  36. os.dup2(f.fileno(), sys.stdin.fileno())
  37. with open(self.stdout, 'ab', 0) as f:
  38. os.dup2(f.fileno(), sys.stdout.fileno())
  39. with open(self.stderr, 'ab', 0) as f:
  40. os.dup2(f.fileno(), sys.stderr.fileno())
  41. # Write the PID file
  42. with open(self.pidfile, 'w') as f:
  43. print(os.getpid(), file=f)
  44. # Arrange to have the PID file removed on exit/signal
  45. atexit.register(lambda: os.remove(self.pidfile))
  46. signal.signal(signal.SIGTERM, self.__sigterm_handler)
  47. # Signal handler for termination (required)
  48. @staticmethod
  49. def __sigterm_handler(signo, frame):
  50. raise SystemExit(1)
  51. def start(self):
  52. try:
  53. self.daemonize()
  54. except RuntimeError as e:
  55. print(e, file=sys.stderr)
  56. raise SystemExit(1)
  57. self.run()
  58. def stop(self):
  59. try:
  60. if os.path.exists(self.pidfile):
  61. with open(self.pidfile) as f:
  62. os.kill(int(f.read()), signal.SIGTERM)
  63. else:
  64. print('Not running.', file=sys.stderr)
  65. raise SystemExit(1)
  66. except OSError as e:
  67. if 'No such process' in str(e) and os.path.exists(self.pidfile):
  68. os.remove(self.pidfile)
  69. def restart(self):
  70. self.stop()
  71. self.start()
  72. def run(self):
  73. #继承类重写该方法
  74. pass