daemonizer.py :  » Development » Pyro » Pyro-3.10 » Pyro » ext » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Pyro 
Pyro » Pyro 3.10 » Pyro » ext » daemonizer.py
#!/usr/bin/env python
#############################################################################
#  
#  $Id: daemonizer.py,v 1.3.2.1 2008/05/05 00:13:03 irmen Exp $
#  Run Pyro servers as daemon processes on Unix/Linux.
#  This won't work on other operating systems such as Windows.
#  Author: Jeff Bauer  (jbauer@rubic.com)
#  This software is released under the MIT software license.
#  Based on an earlier daemonize module by Jeffery Kunce
#  Updated by Luis Camaano to double-fork-detach.
#
#  This is part of "Pyro" - Python Remote Objects
#  which is (c) Irmen de Jong - irmen@users.sourceforge.net
#
#############################################################################

import sys, os, time
from signal import SIGINT

class DaemonizerException:
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return self.msg

class Daemonizer:
    """
    Daemonizer is a class wrapper to run a Pyro server program
    in the background as daemon process.  The only requirement 
    is for the derived class to implement a main_loop() method.
    See Test class below for an example.

    The following command line operations are provided to support
    typical /etc/init.d startup/shutdown on Unix systems:

        start | stop | restart

    In addition, a daemonized program can be called with arguments:

        status  - check if process is still running

        debug   - run the program in non-daemon mode for testing

    Note: Since Daemonizer uses fork(), it will not work on non-Unix
    systems.
    """
    def __init__(self, pidfile=None):
        if not pidfile:
            self.pidfile = "/tmp/%s.pid" % self.__class__.__name__.lower()
        else:
            self.pidfile = pidfile

    def become_daemon(self, root_dir='/'):
        if os.fork() != 0:  # launch child and ...
            os._exit(0)  # kill off parent
        os.setsid()
        os.chdir(root_dir)
        os.umask(0)
        if os.fork() != 0: # fork again so we are not a session leader
            os._exit(0)
        sys.stdin.close()
        sys.__stdin__ = sys.stdin
        sys.stdout.close()
        sys.stdout = sys.__stdout__ = _NullDevice()
        sys.stderr.close()
        sys.stderr = sys.__stderr__ = _NullDevice()
        for fd in range(1024):
            try:
                os.close(fd)
            except OSError:
                pass

    def daemon_start(self, start_as_daemon=1):
        if start_as_daemon:
            self.become_daemon()
        if self.is_process_running():
            msg = "Unable to start server. Process is already running."
            raise DaemonizerException(msg)
        f = open(self.pidfile, 'w')
        f.write("%s" % os.getpid())
        f.close()
        self.main_loop()

    def daemon_stop(self):
        pid = self.get_pid()
        try:
            os.kill(pid, SIGINT)  # SIGTERM is too harsh...
            time.sleep(1)
            try:
                os.unlink(self.pidfile)
            except OSError:
                pass
        except IOError:
            pass

    def get_pid(self):
        try:
            f = open(self.pidfile)
            pid = int(f.readline().strip())
            f.close()
        except IOError:
            pid = None
        return pid

    def is_process_running(self):
        pid = self.get_pid()
        if pid:
            try:
                os.kill(pid, 0)
                return 1
            except OSError:
                pass
        return 0

    def main_loop(self):
        """NOTE: This method must be implemented in the derived class."""
        msg = "main_loop method not implemented in derived class: %s" % \
              self.__class__.__name__
        raise DaemonizerException(msg)

    def process_command_line(self, argv, verbose=1):
        usage = "usage:  %s  start | stop | restart | status | debug " \
                "(run as non-daemon)" % os.path.basename(argv[0])
        if len(argv) < 2:
            print usage
            raise SystemExit
        else:
            operation = argv[1]
        pid = self.get_pid()
        if operation == 'status':
            if self.is_process_running():
                print "Server process %s is running." % pid
            else:
                print "Server is not running."
        elif operation == 'start':
            if self.is_process_running():
                print "Server process %s is already running." % pid
                raise SystemExit
            else:
                if verbose:
                    print "Starting server process."
                self.daemon_start()
        elif operation == 'stop':
            if self.is_process_running():
                self.daemon_stop()
                if verbose:
                    print "Server process %s stopped." % pid
            else:
                print "Server process %s is not running." % pid
                raise SystemExit
        elif operation == 'restart':
            self.daemon_stop()
            if verbose:
                print "Restarting server process."
            self.daemon_start()
        elif operation == 'debug':
            self.daemon_start(0)
        else:
            print "Unknown operation:", operation
            raise SystemExit


class _NullDevice:
    """A substitute for stdout/stderr that writes to nowhere."""
    def write(self, s):
        pass


class Test(Daemonizer):
    def __init__(self):
        Daemonizer.__init__(self)

    def main_loop(self):
        while 1:
            time.sleep(1)


if __name__ == "__main__":
    test = Test()
    test.process_command_line(sys.argv)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.