一个别人写的模块,可以直接用来把一个普通进程改为守护进程。
并且自动把标准输出重定向到日志文件,很实用啊。
- <BR>
- '''''<BR>
- This module is used to fork the current process into a daemon.<BR>
- Almost none of this is necessary (or advisable) if your daemon <BR>
- is being started by inetd. In that case, stdin, stdout and stderr are <BR>
- all set up for you to refer to the network connection, and the fork()s <BR>
- and session manipulation should not be done (to avoid confusing inetd). <BR>
- Only the chdir() and umask() steps remain as useful.<BR>
- References:<BR>
- UNIX Programming FAQ<BR>
- 1.7 How do I get my program to act like a daemon?<BR>
- [url]http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16[/url]<BR>
- Advanced Programming in the Unix Environment<BR>
- W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.<BR>
- <BR>
- History:<BR>
- 2001/07/10 by Juergen Hermann<BR>
- 2002/08/28 by Noah Spurrier<BR>
- 2003/02/24 by Clark Evans<BR>
- 2003/11/01 by Irmen de Jong --- adapted a bit for Snakelets<BR>
- (raises exception at certain points)<BR>
- <BR>
- [url]http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012[/url]<BR>
- '''<BR>
- import sys, os, time<BR>
- from signal import SIGINT,SIGTERM,SIGKILL<BR>
- <BR>
- def daemonize(stdout='/dev/null', stderr=None, stdin='/dev/null',<BR>
- pidfile=None, startmsg = 'started with pid %s' ):<BR>
- '''''<BR>
- This forks the current process into a daemon.<BR>
- The stdin, stdout, and stderr arguments are file names that<BR>
- will be opened and be used to replace the standard file descriptors<BR>
- in sys.stdin, sys.stdout, and sys.stderr.<BR>
- These arguments are optional and default to /dev/null.<BR>
- Note that stderr is opened unbuffered, so<BR>
- if it shares a file with stdout then interleaved output<BR>
- may not appear in the order that you expect.<BR>
- '''<BR>
- <BR>
- # flush io<BR>
- sys.stdout.flush()<BR>
- sys.stderr.flush()<BR>
- <BR>
- # Do first fork.<BR>
- try: <BR>
- pid = os.fork() <BR>
- if pid > 0: sys.exit(0) # Exit first parent.<BR>
- except OSError, e: <BR>
- sys.stderr.write("fork #1 failed: (%d) %s/n" % (e.errno, e.strerror))<BR>
- sys.exit(1)<BR>
- <BR>
- # Decouple from parent environment.<BR>
- os.chdir("/") <BR>
- os.umask(0) <BR>
- os.setsid() <BR>
- <BR>
- # Do second fork.<BR>
- try: <BR>
- pid = os.fork() <BR>
- if pid > 0: sys.exit(0) # Exit second parent.<BR>
- except OSError, e: <BR>
- sys.stderr.write("fork #2 failed: (%d) %s/n" % (e.errno, e.strerror))<BR>
- sys.exit(1)<BR>
- <BR>
- # Open file descriptors and print start message<BR>
- if not stderr: stderr = stdout<BR>
- si = file(stdin, 'r')<BR>
- so = file(stdout, 'a+') <BR>
- se = file(stderr, 'a+', 0) #unbuffered<BR>
- pid = str(os.getpid())<BR>
- sys.stderr.write("/n%s/n" % startmsg % pid)<BR>
- sys.stderr.flush()<BR>
- if pidfile: file(pidfile,'w+').write("%s/n" % pid)<BR>
- <BR>
- # Redirect standard file descriptors.<BR>
- os.dup2(si.fileno(), sys.stdin.fileno())<BR>
- os.dup2(so.fileno(), sys.stdout.fileno())<BR>
- os.dup2(se.fileno(), sys.stderr.fileno())<BR>
- <BR>
- <BR>
- class DaemonizeError(Exception): pass<BR>
- <BR>
- <BR>
- def startstop(stdout='/dev/null', stderr=None, stdin='/dev/null',<BR>
- pidfile='pid.txt', startmsg = 'started with pid %s', action=None ):<BR>
- <BR>
- if not action and len(sys.argv) > 1:<BR>
- action = sys.argv[1]<BR>
- <BR>
- if action:<BR>
- try:<BR>
- pf = file(pidfile,'r')<BR>
- pid = int(pf.read().strip())<BR>
- pf.close()<BR>
- except IOError:<BR>
- pid = None<BR>
- if 'stop' == action or 'restart' == action:<BR>
- if not pid:<BR>
- mess = "Could not stop, pid file '%s' missing./n"<BR>
- raise DaemonizeError(mess % pidfile)<BR>
- try:<BR>
- while 1:<BR>
- print "sending SIGINT to",pid<BR>
- os.kill(pid,SIGINT)<BR>
- time.sleep(2)<BR>
- print "sending SIGTERM to",pid<BR>
- os.kill(pid,SIGTERM)<BR>
- time.sleep(2)<BR>
- print "sending SIGKILL to",pid<BR>
- os.kill(pid,SIGKILL)<BR>
- time.sleep(1)<BR>
- except OSError, err:<BR>
- print "process has been terminated."<BR>
- os.remove(pidfile)<BR>
- if 'stop' == action:<BR>
- return ## sys.exit(0)<BR>
- action = 'start'<BR>
- pid = None<BR>
- if 'start' == action:<BR>
- if pid:<BR>
- mess = "Start aborted since pid file '%s' exists. Server still running?/n"<BR>
- raise DaemonizeError(mess % pidfile)<BR>
- daemonize(stdout,stderr,stdin,pidfile,startmsg)<BR>
- return<BR>
- print "usage: %s start|stop|restart" % sys.argv[0]<BR>
- raise DaemonizeError("invalid command")<BR>
- <BR>
- def test():<BR>
- '''''<BR>
- This is an example main function run by the daemon.<BR>
- This prints a count and timestamp once per second.<BR>
- '''<BR>
- sys.stdout.write ('Message to stdout...')<BR>
- sys.stderr.write ('Message to stderr...')<BR>
- c = 0<BR>
- while 1:<BR>
- sys.stdout.write ('%d: %s/n' % (c, time.ctime(time.time())) )<BR>
- sys.stdout.flush()<BR>
- c = c + 1<BR>
- time.sleep(1)<BR>
- <BR>
- if __name__ == "__main__":<BR>
- startstop(stdout='/tmp/daemonize.log',<BR>
- pidfile='/tmp/daemonize.pid')<BR>
- if sys.argv[1]in ('start', 'restart'):<BR>
- test()<BR>