|
|
(9 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| [[Category:Engineering]] | | [[Category:Engineering]] |
| [[Category:Python]] | | [[Category:Python]] |
− | == Python Daemonize source ==
| + | [[Category:Free_Software]] |
− | <pre>
| |
− | #!/usr/bin/env python
| |
− | import sys, os, signal
| |
| | | |
− | '''This module is used to fork the current process into a daemon.
| + | This short module shows the correct way to create a UNIX daemon process in Python. |
| | | |
− | Almost none of this is necessary (or advisable) if your daemon
| + | Click here to download: [http://www.noah.org/engineering/src/python/daemonize.py daemonize.py] |
− | is being started by inetd. In that case, stdin, stdout and stderr are
| + | <include src="/home/noahspurrier/noah.org/engineering/src/python/daemonize.py" highlight="python" /> |
− | all set up for you to refer to the network connection, and the fork()s
| |
− | and session manipulation should not be done (to avoid confusing inetd).
| |
− | Only the chdir() and umask() steps remain as useful.
| |
− | | |
− | References:
| |
− | UNIX Programming FAQ
| |
− | 1.7 How do I get my program to act like a daemon?
| |
− | http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
| |
− |
| |
− | Advanced Programming in the Unix Environment
| |
− | W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.
| |
− | '''
| |
− | | |
− | def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
| |
− | '''This forks the current process into a daemon.
| |
− | The stdin, stdout, and stderr arguments are file names that
| |
− | will be opened and be used to replace the standard file descriptors
| |
− | in sys.stdin, sys.stdout, and sys.stderr.
| |
− | These arguments are optional and default to /dev/null.
| |
− | Note that stderr is opened unbuffered, so
| |
− | if it shares a file with stdout then interleaved output
| |
− | may not appear in the order that you expect.
| |
− | '''
| |
− | | |
− | # Do first fork.
| |
− | try:
| |
− | pid = os.fork()
| |
− | if pid > 0:
| |
− | return pid
| |
− | except OSError, e:
| |
− | return (e.errno, e.strerror) # Fork failed.
| |
− | | |
− | # Decouple from parent environment.
| |
− | os.setsid()
| |
− | | |
− | # When the first child terminates, all processes in the second child
| |
− | # are sent a SIGHUP. This causes it to be ignored.
| |
− | signal.signal(signal.SIGHUP, signal.SIG_IGN)
| |
− | | |
− | # Do second fork.
| |
− | try:
| |
− | pid = os.fork()
| |
− | if pid > 0:
| |
− | os._exit(0) # Exit second parent.
| |
− | except OSError, e:
| |
− | sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) )
| |
− | os._exit(1)
| |
− | | |
− | # Now I am a daemon!
| |
− |
| |
− | os.chdir("/") # don't hold open any directories
| |
− | os.umask(0)
| |
− | | |
− | # Close open files. Try the system configuration variable, SC_OPEN_MAX,
| |
− | # for the maximum number of open files to close. If it doesn't exist, use 1024.
| |
− | try:
| |
− | maxfd = os.sysconf("SC_OPEN_MAX")
| |
− | except (AttributeError, ValueError):
| |
− | maxfd = 1024
| |
− | for fd in range(3, maxfd):
| |
− | try:
| |
− | os.close(fd)
| |
− | except OSError: # ERROR (ignore)
| |
− | pass
| |
− | | |
− | # Redirect standard file descriptors.
| |
− | si = open(stdin, 'r')
| |
− | so = open(stdout, 'a+')
| |
− | se = open(stderr, 'a+', 0)
| |
− | os.dup2(si.fileno(), sys.stdin.fileno())
| |
− | os.dup2(so.fileno(), sys.stdout.fileno())
| |
− | os.dup2(se.fileno(), sys.stderr.fileno())
| |
− | return 0
| |
− | | |
− | def main ():
| |
− | '''This is an example main function run by the daemon.
| |
− | This prints a count and timestamp once per second.
| |
− | '''
| |
− | import time
| |
− | sys.stdout.write ('Daemon started with pid %d\n' % os.getpid() )
| |
− | sys.stdout.write ('Daemon stdout output\n')
| |
− | sys.stderr.write ('Daemon stderr output\n')
| |
− | c = 0
| |
− | while 1:
| |
− | sys.stdout.write ('%d: %s\n' % (c, time.ctime(time.time())) )
| |
− | sys.stdout.flush()
| |
− | c = c + 1
| |
− | time.sleep(1)
| |
− | | |
− | if __name__ == "__main__":
| |
− | print str(daemonize('/dev/null','/tmp/daemon.log','/tmp/daemon.log'))
| |
− | main()
| |
− | </pre>
| |