123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- # -*- coding: utf-8 -*-
- import os
- import sys
- import time
- import atexit
- import signal
- from demeter.core import *
- class Daemon(object):
- name = 'demeter'
- def __init__(self, key='daemon', path='/tmp/', stdin='/dev/null', stdout=True, stderr=True):
- self.key = key
- self.path = path + self.name + '_' + key + '/'
- File.mkdir(self.path)
- if stdout == False:
- stdout = '/dev/null'
- else:
- stdout = self.path + 'out.log'
- if stderr == False:
- stderr = '/dev/null'
- else:
- stdout = self.path + 'err.log'
- self.stdin = stdin
- self.stdout = stdout
- self.stderr = stderr
- self.pid = self.path + self.key + '.pid'
- def daemonize(self):
- if os.path.exists(self.pid):
- raise RuntimeError('Already running.')
- # First fork (detaches from parent)
- try:
- if os.fork() > 0:
- raise SystemExit(0)
- except OSError as e:
- raise RuntimeError('fork #1 faild: {0} ({1})\n'.format(e.errno, e.strerror))
- os.chdir('/')
- os.setsid()
- os.umask(0o22)
- # Second fork (relinquish session leadership)
- try:
- if os.fork() > 0:
- raise SystemExit(0)
- except OSError as e:
- raise RuntimeError('fork #2 faild: {0} ({1})\n'.format(e.errno, e.strerror))
- # Flush I/O buffers
- sys.stdout.flush()
- sys.stderr.flush()
- # Replace file descriptors for stdin, stdout, and stderr
- with open(self.stdin, 'rb', 0) as f:
- os.dup2(f.fileno(), sys.stdin.fileno())
- with open(self.stdout, 'ab', 0) as f:
- os.dup2(f.fileno(), sys.stdout.fileno())
- with open(self.stderr, 'ab', 0) as f:
- os.dup2(f.fileno(), sys.stderr.fileno())
- # Write the PID file
- with open(self.pid, 'w') as f:
- print(os.getpid(), file=f)
- # Arrange to have the PID file removed on exit/signal
- atexit.register(lambda: File.remove(self.pid))
- signal.signal(signal.SIGTERM, self.__sigterm_handler)
- # Signal handler for termination (required)
- @staticmethod
- def __sigterm_handler(signo, frame):
- raise SystemExit(1)
- def start(self):
- try:
- self.daemonize()
- except RuntimeError as e:
- print(e, file=sys.stderr)
- raise SystemExit(1)
- self.run()
- def stop(self):
- try:
- if File.exists(self.pid):
- with open(self.pid) as f:
- os.kill(int(f.read()), signal.SIGTERM)
- else:
- print('Not running.', file=sys.stderr)
- raise SystemExit(1)
- except OSError as e:
- if 'No such process' in str(e) and File.exists(self.pid):
- File.remove(self.pid)
- def restart(self):
- self.stop()
- self.start()
- def run(self):
- pass
|