Created
May 14, 2013 04:21
Revisions
-
Jd007 created this gist
May 14, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,132 @@ import sys, os, time, atexit from signal import SIGTERM class Daemon: ''' Base Daemon class that takes care of the start, stop, and forking of the processes. Used to daemonize any Python script. ''' def __init__(self, pidfile, worker_id, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): self.pidfile = pidfile self.worker_id = worker_id self.stdin = stdin self.stdout = stdout self.stderr = stderr self.init_time = int(time.time()) self.successful_job_count = 0 self.failed_job_count = 0 self.avg_job_time = 0 def daemonize(self): ''' Double-forks the process to daemonize the script. ''' try: pid = os.fork() if pid > 0: # Exit from first parent sys.exit(0) except OSError, e: sys.stderr.write("Fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) # Decouple from parent environment os.chdir("/") os.setsid() os.umask(0) # Second fork try: pid = os.fork() if pid > 0: # Exit from second parent sys.exit(0) except OSError, e: sys.stderr.write("Fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) # Redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() si = file(self.stdin, 'r') so = file(self.stdout, 'a+') se = file(self.stderr, 'a+', 0) os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) # Write the PID file atexit.register(self.delpid) pid = str(os.getpid()) file(self.pidfile, 'w+').write("%s\n" % pid) def delpid(self): # Removes the PID file os.remove(self.pidfile) def start(self): ''' Start the daemon. ''' # Check for a PID file to see if the Daemon is already running try: pf = file(self.pidfile, 'r') pid = int(pf.read().strip()) pf.close() except IOError: pid = None if pid: message = "PID file %s already exist. Daemon already running?\n" sys.stderr.write(message % self.pidfile) sys.exit(1) # No PID file, start the daemon self.daemonize() self.run() def stop(self): ''' Stop the daemon. ''' # Get the PID from the PID file try: pf = file(self.pidfile, 'r') pid = int(pf.read().strip()) pf.close() except IOError: pid = None if not pid: message = "PID file %s does not exist. Daemon not running?\n" sys.stderr.write(message % self.pidfile) return # not an error in a restart # Try to kill the daemon process try: while 1: os.kill(pid, SIGTERM) time.sleep(0.1) except OSError, err: err = str(err) if err.find("No such process") > 0: if os.path.exists(self.pidfile): os.remove(self.pidfile) else: print str(err) sys.exit(1) def restart(self): ''' Restart the daemon. ''' self.stop() self.start() def run(self): ''' The script to execute by the daemon after it starts. ''' pass