参考:http://www.tsheffler.com/blog/?p=377
-
# -*- coding: utf-8 -*-
-
'''
-
This module is used to fork the current process into a daemon.
-
Almost none of this is necessary (or advisable) if your daemon
-
is being started by inetd. In that case, stdin, stdout and stderr are
-
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?
-
-
Advanced Programming in the Unix Environment
-
W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.
-
-
History:
-
2001/07/10 by Jürgen Herman
-
2002/08/28 by Noah Spurrier
-
2003/02/24 by Clark Evans
-
-
-
'''
-
import sys, os, time
-
from signal import SIGTERM
-
-
def deamonize(stdout='/dev/null', stderr=None, stdin='/dev/null',
-
pidfile=None, startmsg = 'started with pid %s' ):
-
'''
-
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: sys.exit(0) # Exit first parent.
-
except OSError, e:
-
sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
-
sys.exit(1)
-
# Decouple from parent environment.
-
os.chdir("/")
-
os.umask(0)
-
os.setsid()
-
-
# Do second fork.
-
try:
-
pid = os.fork()
-
if pid > 0: sys.exit(0) # Exit second parent.
-
except OSError, e:
-
sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
-
sys.exit(1)
-
-
# Open file descriptors and print start message
-
if not stderr: stderr = stdout
-
si = file(stdin, 'r')
-
so = file(stdout, 'a+')
-
se = file(stderr, 'a+', 0)
-
pid = str(os.getpid())
-
sys.stderr.write("\n%s\n" % startmsg % pid)
-
sys.stderr.flush()
-
if pidfile: file(pidfile,'w+').write("%s\n" % pid)
-
-
# Redirect standard file descriptors.
-
os.dup2(si.fileno(), sys.stdin.fileno())
-
os.dup2(so.fileno(), sys.stdout.fileno())
-
os.dup2(se.fileno(), sys.stderr.fileno())
-
-
def startstop(stdout='/dev/null', stderr=None, stdin='/dev/null',
-
pidfile='pid.txt', startmsg = 'started with pid %s' ):
-
if len(sys.argv) > 1:
-
action = sys.argv[1]
-
try:
-
pf = file(pidfile,'r')
-
pid = int(pf.read().strip())
-
pf.close()
-
except IOError:
-
pid = None
-
if 'stop' == action or 'restart' == action:
-
if not pid:
-
mess = "Could not stop, pid file '%s' missing.\n"
-
sys.stderr.write(mess % pidfile)
-
sys.exit(1)
-
try:
-
while 1:
-
os.kill(pid,SIGTERM)
-
time.sleep(1)
-
except OSError, err:
-
err = str(err)
-
if err.find("No such process") > 0:
-
os.remove(pidfile)
-
if 'stop' == action:
-
sys.exit(0)
-
action = 'start'
-
pid = None
-
else:
-
print str(err)
-
sys.exit(1)
-
if 'start' == action:
-
if pid:
-
mess = "Start aborded since pid file '%s' exists.\n"
-
sys.stderr.write(mess % pidfile)
-
sys.exit(1)
-
deamonize(stdout,stderr,stdin,pidfile,startmsg)
-
return
-
print "usage: %s start|stop|restart" % sys.argv[0]
-
sys.exit(2)
-
-
def test():
-
'''
-
This is an example main function run by the daemon.
-
This prints a count and timestamp once per second.
-
'''
-
sys.stdout.write ('Message to stdout...')
-
sys.stderr.write ('Message to stderr...')
-
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__":
-
startstop(stdout='/tmp/deamonize.log',
-
pidfile='/tmp/deamonize.pid')
-
test()
使用的时候:
-
SIGTERM_SENT = False
-
-
def sigterm_handler(signum, frame):
-
print >>sys.stderr, "SIGTERM handler. Shutting Down."
-
-
global SIGTERM_SENT
-
if not SIGTERM_SENT:
-
SIGTERM_SENT = True
-
print >>sys.stderr, "Sending TERM to PG"
-
os.killpg(0, signal.SIGTERM)
-
-
sys.exit()
-
-
def main():
-
# set session ID to this process so we can kill group in sigterm handler
-
os.setsid()
-
signal.signal(signal.SIGTERM, sigterm_handler)
-
-
while True:
-
# ... run daemon threads and subprocesses with impunity.
-
-
# ... this function never returns ...
-
-
from daemonize import startstop
-
-
if __name__== "__main__":
-
startstop(stdout="/var/log/example.log",
-
pidfile="/var/run/example.pid")
-
main()
main函数中的os.setsid()的作用是将daemon进程设为会话ID。然后退出的时候用os
.killpg
(0
, signal
.SIGTERM
)将进程组杀掉就可以了。
阅读(1724) | 评论(0) | 转发(0) |