"""Generic linux daemon base class for python 3.x.""" import uuid import sys import os import time import threading class daemon(object): """A generic daemon class. Usage: subclass the daemon class and override the run() method.""" def __init__(self): self._thread = threading.Thread(target=self.test, name='task_queue', daemon=True) def test(self): for i in range(3): print('running loop %s' % i) time.sleep(1) def daemonize(self): """Daemonizes the current process. Returns the new pid""" try: pid = os.fork() if pid > 0: # exit first parent sys.exit(0) except OSError as err: sys.stderr.write('fork #1 failed: {0}\n'.format(err)) sys.exit(1) # decouple from parent environment os.chdir('/') os.setsid() os.umask(0) print('First fork pid %s' % os.getpid()) # do second fork try: pid = os.fork() if pid > 0: # exit from second parent sys.exit(0) except OSError as err: sys.stderr.write('fork #2 failed: {0}\n'.format(err)) sys.exit(1) # redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() si = open(os.devnull, 'r') so = open('/tmp/file', 'a+') se = open('/tmp/file', 'a+') os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) def start(self): """Start the daemon.""" # Start the daemon self.daemonize() self._thread.start() self.wait() def wait(self): """ Waits for the thread to exit. Allows abortion of task queue with ctrl-c """ try: print('thread alive is %s' % self._thread.is_alive()) while self._thread.is_alive(): print('pid %s wait sleep thread alive is %s' % (os.getpid(), self._thread.is_alive())) time.sleep(0.5) except KeyboardInterrupt: print('Got ctrl-c, shutting down after running task (if any) completes') # We still wait to finish cleanly, pressing ctrl-c again will abort while self._thread.is_alive(): time.sleep(0.5) d = daemon() d.start()