# -*- coding: utf-8-*- # # This file is part of stdd, the simple time display daemon, # written by Helmut Pozimski , # licensed under the 3-clause BSD license import os import sys class Daemon(object): """ Tries to implement a well behaving unix daemon in a generic way, so the code could be used in different projects. """ def __init__(self, pfile_path, pfile_name): """ Initializes the object. """ self.__pfile_path = pfile_path self.__pfile_name = pfile_name self.__daemon = False def Daemonize(self): """ Turns the calling prozess into a daemon running on it's own """ try: # Fork for the first time self.__pid = os.fork() except OSError: sys.exit(os.EX_OSERR) else: if self.__pid > 0: sys.exit(os.EX_OK) # Become session and group leader os.setsid() try: #Fork for the second time self.__pid = os.fork() except OSError: sys.exit(os.EX_OSERR) else: if self.__pid > 0: sys.exit(os.EX_OK) # Change cwd to / to avoid interfering with other mounted file systems os.chdir("/") # Reset the umask os.umask(0) # Close possibly open file descriptors os.close(0) os.close(1) os.close(2) # And redirect them to /dev/null os.open("/dev/null", 0) os.open("/dev/null", 1) os.open("/dev/null", 2) self.__daemon = True def DropPriv(self, uid, gid): """ If the daemon is running as root user, drop privileges and continue running as the defined unprivileged user """ if os.getuid() == 0: os.setgid(gid) os.setuid(uid) def SetName(self, name, cmdline): """ Sets the name of the process shown visible in ps and top, this allows to make your daemon look more like a standalone program instead of a python script. """ try: # First check if prctl is available, otherwise this function does nothing import prctl except ImportError: return False else: prctl.set_name(name) prctl.set_proctitle(cmdline) return True def Start(self): """ Performs the operations needed to "start" the daemon """ if self.__daemon is True: if os.access(self.__pfile_path, os.F_OK & os.W_OK): self.__pidfile = open(os.path.join(self.__pfile_path, self.__pfile_name), "w") self.__pidfile.write(unicode(os.getpid()) + "\n") self.__pidfile.close() return True else: return False else: return False def Stop(self): """ Performs the operations needed to stop the daemon """ if self.__daemon is True: try: os.remove(os.path.join(self.__pfile_path, self.__pfile_name)) except OSError: return False else: return True else: return True