diff --git a/daemonic/daemon.py b/daemonic/daemon.py index b6af181..68c6e8b 100644 --- a/daemonic/daemon.py +++ b/daemonic/daemon.py @@ -9,8 +9,9 @@ import atexit import signal import time +import pwd -import pidfile +import daemonic.pidfile class daemon(object): 'Context manager for POSIX daemon processes' @@ -22,10 +23,13 @@ def __init__(self, stdin=None, stdout=None, stderr=None, + user=None ): self.pidfile = pidfile self.workingdir = workingdir self.umask = umask + self.daemon_user = user + self.old_env = os.environ.copy() devnull = os.open(os.devnull, os.O_RDWR) self.stdin = stdin.fileno() if stdin is not None else devnull @@ -71,22 +75,39 @@ def daemonize(self): if self.pidfile is not None: pid = str(os.getpid()) try: - pidfile.make_pidfile(self.pidfile, pid) - except pidfile.PIDFileError as e: - sys.stederr.write('Creating PID file failed. ({})'.format(e)) + daemonic.pidfile.make_pidfile(self.pidfile, pid) + except daemonic.pidfile.PIDFileError as e: + sys.stderr.write('Creating PID file failed. ({})'.format(e)) os._exit(os.EX_OSERR) + + # Change user if need + if self.daemon_user is not None: + pw_record = pwd.getpwnam(self.daemon_user) + user_name = pw_record.pw_name + user_home_dir = pw_record.pw_dir + user_uid = pw_record.pw_uid + user_gid = pw_record.pw_gid + env = os.environ.copy() + env[ 'HOME' ] = user_home_dir + env[ 'LOGNAME' ] = user_name + env[ 'USER' ] = user_name + os.setgid(user_gid) + os.setuid(user_uid) + os.environ = env + atexit.register(self.stop) def stop(self): + os.environ = self.old_env if self.pidfile is not None: - pid = pidfile.readpid(self.pidfile) + pid = daemonic.pidfile.readpid(self.pidfile) try: while True: - os.kill(pid, signal.SIGTERM) + os.kill(int(pid), signal.SIGTERM) time.sleep(0.1) except OSError as e: if e.errno == errno.ESRCH: - pidfile.remove_pidfile(self.pidfile) + daemonic.pidfile.remove_pidfile(self.pidfile) else: raise @@ -96,6 +117,6 @@ def _getchildfork(n): if pid > 0: sys.exit(os.EX_OK) # Exit in parent except OSError as e: - sys.stederr.write('Fork #{} failed: {} ({})\n'.format( + sys.stderr.write('Fork #{} failed: {} ({})\n'.format( n, e.errno, e.strerror)) os._exit(os.EX_OSERR) diff --git a/daemonic/pidfile.py b/daemonic/pidfile.py index 2b68b87..f03c6f0 100644 --- a/daemonic/pidfile.py +++ b/daemonic/pidfile.py @@ -52,6 +52,7 @@ def is_pid_running(pid): def make_pidfile(path, pid): '''Create a PID file. ''' + fd = None try: fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL) except OSError as e: