-
-
Save thebookworm101/5936692 to your computer and use it in GitHub Desktop.
This file contains 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 characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment