← Daemon Download

#!/usr/bin/python3 ################################################################################ # POSIX daemon. # ################################################################################ import atexit import os import signal import sys import time class Daemon: ############################################################################ # Construct. # ############################################################################ def __init__(self): # Set PID file. self.pidfile = '/var/run/' + self.__class__.__name__.lower() + '.pid' ############################################################################ # Start daemon. # ############################################################################ def start(self): # Feedback. sys.stdout.write('Starting: ') # Check if daemon is already running. try: with open(self.pidfile, 'r') as file: pid = int(file.read().strip()) if pid: sys.stdout.write('[ \033[91mFailed\033[0m ]\n') except: pass # Fork process. try: if os.fork() > 0: sys.exit(0) except Exception as error: sys.stdout.write('[ \033[91mFailed\033[0m ]\n') sys.exit(1) # Decouple. os.chdir('/') os.setsid() os.umask(0) # Fork process again. try: if os.fork() > 0: sys.exit(0) except OSError as error: sys.stdout.write('[ \033[91mFailed\033[0m ]\n') sys.exit(1) # Feedback. sys.stdout.write('[ \033[92mOK\033[0m ]\n') # Wipe output buffers. sys.stdout.flush() sys.stderr.flush() # Redirect input/outputs. stdin = open(os.devnull, 'r') stdout = open(os.devnull, 'a+') stderr = open(os.devnull, 'a+') # Duplicate file descriptors. os.dup2(stdin.fileno(), sys.stdin.fileno()) os.dup2(stdout.fileno(), sys.stdout.fileno()) os.dup2(stderr.fileno(), sys.stderr.fileno()) # Delete PID file on exit. atexit.register(os.remove(self.pidfile)) # Write pidfile. with open(self.pidfile, 'w+') as file: file.write(str(os.getpid()) + '\n') # Run main program loop. self.run() ############################################################################ # Stop daemon. # ############################################################################ def stop(self): # Feedback. sys.stdout.write('Stopping: ') # Get the PID from the PID file. try: with open(self.pidfile, 'r') as file: pid = int(file.read().strip()) except: pid = None if not pid: sys.stdout.write('[ \033[91mFailed\033[0m ]\n') return # Kill process using PID. try: while 1: os.kill(pid, signal.SIGTERM) time.sleep(0.1) except OSError as error: sys.stdout.write('[ \033[91mFailed\033[0m ]\n') error = str(error.args) if error.find('No such process') > 0: if os.path.exists(self.pidfile): os.remove(self.pidfile) else: sys.stderr.write('Error: ' + error) sys.exit(1) sys.stdout.write('[ \033[92mOK\033[0m ]\n') ############################################################################ # Restart daemon. # ############################################################################ def restart(self): self.stop() self.start() ############################################################################ # Get status of daemon. # ############################################################################ def status(self): # Get the PID from the PID file. try: with open(self.pidfile, 'r') as file: pid = int(file.read().strip()) except: pid = None if not pid: sys.stderr.write(self.__class__.__name__.lower() + ' is not running') return sys.stdout.write(' (pid ' + pid + ') is running...') ############################################################################ # Main program loop. # ############################################################################ def run(self): while 1: # Throttle time.sleep(1) # Do stuff. with open(self.pidfile, 'a+') as file: file.write('Still here! \n') ################################################################################ # Initializer. # ################################################################################ if __name__ == '__main__': if len(sys.argv) == 2: if 'start' == sys.argv[1]: Daemon().start() elif 'stop' == sys.argv[1]: Daemon().stop() elif 'restart' == sys.argv[1]: Daemon().restart() elif 'status' == sys.argv[1]: Daemon().status() else: print('Unknown command: ' + sys.argv[1]) sys.exit(2) sys.exit(0) else: print('Usage: ' + sys.argv[0] + ' start|stop|restart|status') sys.exit(2)