Lech Karol Pawłaszek wrote:

> Hello.
> 
> I'm trying to make a daemon and I want to log to a file its activity.
> I'm using logging module with a configuration file for it (loaded via
> fileConfig()).
> 
> And now I want to read logging config file before daemonize the program
> because the file might not be accessible after daemonization. OTOH while
> daemonizing I am closing all opened file descriptors - including those
> opened for logging.
> 
> What is the best approach to handle such situation? Should I close all
> FD before daemonizing or just forget it? Any other hints?
> 
> Kind regards,
> 
I use this, YMMV:
import os
import sys
import socket
#WORKDIR = "/"

def gen_name():
    return sys.argv[0] + '.' + socket.gethostname() + '.' + str(os.getpid())

def daemonize(log_stdout=False, out_name=None, log_stderr=False, err_name=None):
    """
    Turn current process into a daemon
    """
    pid = os.fork()
    if (pid == 0):
##        os.chdir (workdir)
        os.setsid()
        maxfd = os.sysconf("SC_OPEN_MAX")
        for fd in range(0, maxfd):
            try:
                os.close(fd)
            except OSError:   # ERROR (ignore)
                pass

        # Redirect the standard file descriptors to /dev/null.
        os.open("/dev/null", os.O_RDONLY)    # standard input (0)
        os.open("/dev/null", os.O_RDWR)       # standard output (1)
        os.open("/dev/null", os.O_RDWR)       # standard error (2)


        if (not out_name):
            out_name = gen_name() + '.out'
        if (not err_name):
            err_name = gen_name() + '.err'
        if (log_stdout):
            sys.stdout = logger (out_name)
        if (log_stderr):
            sys.stderr = logger (err_name)
    else:
        print "forked pid", pid
        sys.exit (0)

import atexit
class logger (object):
    def __init__ (self, name):
        self.name = name               # final file name
        self.f = open (self.name, 'w')
        atexit.register (self.__del__)
    def write (self, stuff):
        self.f.write (stuff)
    def close (self):
        self.f.close()
    def flush (self):
        self.f.flush()
    def reopen (self):
        self.f.flush()
        self.f.close()
        os.rename (self.name, self.name + '.old')
        self.f = open (self.name, 'w')
    def __del__ (self):
        try:
            os.remove (self.name + '.old')
        except:
            pass

        
#install handler
import signal
def handler (signum, frame):
    print >> sys.stderr, "bye bye"
    daemonize (log_stderr=True)

signal.signal (signal.SIGUSR1, handler)

if (__name__ == '__main__'):

##    daemonize (log_stdout=True, out_name='main.out', log_stderr=True, err_name='main.err', err_maxbytes=100)
    daemonize (log_stdout=True, log_stderr=True)

    print "hello, this is stdout"
    print "hello, this is also stdout"
    print >> sys.stderr, "hello, this is stderr"

    sys.stderr.reopen()
    print >> sys.stderr, "stderr has been reopened"

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to