|
@@ -9,100 +9,118 @@ 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.
|
|
|
+ """ 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 __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 """
|
|
|
+ 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)
|
|
|
+ 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)
|
|
|
+ # 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)
|
|
|
+ # And redirect them to /dev/null
|
|
|
+ os.open("/dev/null", 0)
|
|
|
+ os.open("/dev/null", 1)
|
|
|
+ os.open("/dev/null", 2)
|
|
|
|
|
|
- self.__daemon = True
|
|
|
+ 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 DropPriv(self, user, group):
|
|
|
+ """ If the daemon is running as root user, drop privileges and continue
|
|
|
+ running as the defined unprivileged user. """
|
|
|
+ pid_file_path = os.path.join(self.__pfile_path, self.__pfile_name)
|
|
|
+ passwd_file = open("/etc/passwd", "r")
|
|
|
+ group_file = open("/etc/group", "r")
|
|
|
+ uid = ""
|
|
|
+ gid = ""
|
|
|
+ for line in passwd_file:
|
|
|
+ if user in line:
|
|
|
+ uid = line.split(":")[2]
|
|
|
+ break
|
|
|
+ for line in group_file:
|
|
|
+ if group in line.split(":")[0]:
|
|
|
+ gid = line.split(":")[2]
|
|
|
+ break
|
|
|
+ passwd_file.close()
|
|
|
+ group_file.close()
|
|
|
+ if os.getuid() == 0:
|
|
|
+ os.chown(pid_file_path, int(uid), int(gid))
|
|
|
+ os.setgid(int(gid))
|
|
|
+ os.setuid(int(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.
|
|
|
+ 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
|
|
|
+ """
|
|
|
+ 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 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
|
|
|
+ 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
|