运行的时候,建立一个进程,linux会分配个进程号。然后调用os.fork()创建子进程。若pid>0就是自己,自杀。子进程跳过if语句,通过os.setsid()成为linux中的独立于终端的进程(不响应sigint,sighup等)。
第二次os.fork再创建一个子进程,自己自杀。原因是os.setsid()后成为父进程,虽然已经不被动响应信号,但访问终端文件时控制权还是会失去。这次创建的进程真的是孤魂野鬼的daemon,并且外界对它影响被控制在最小。
#!/usr/bin/python# -*- coding: utf-8 -*-import sys, os, time, atexit
from signal
import SIGTERM
class Daemon:
""" A generic daemon class. Usage: subclass the Daemon class and override the _run() method """ def __init__(self, pidfile, stdin=
'/dev/null', stdout=
'/dev/null', stderr=
'/dev/null'): self.stdin = stdin self.stdout = stdout self.stderr = stderr self.pidfile = pidfile
def _daemonize(self):
""" do the UNIX double-fork magic, see Stevens' "Advanced Programming in the UNIX Environment" for details (ISBN 0201563177) http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 """ #脱离父进程 try: pid = os.fork()
if pid >
0: sys.exit(
0)
except OSError, e: sys.stderr.write(
"fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(
1)
#脱离终端 os.setsid()
#修改当前工作目录 os.chdir(
"/")
#重设文件创建权限 os.umask(
0)
#第二次fork,禁止进程重新打开控制终端 try: pid = os.fork()
if pid >
0: sys.exit(
0)
except OSError, e: sys.stderr.write(
"fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(
1) sys.stdout.flush() sys.stderr.flush() si =
file(self.stdin,
'r') so =
file(self.stdout,
'a+') se =
file(self.stderr,
'a+',
0)
#重定向标准输入/输出/错误 os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno())
#注册程序退出时的函数,即删掉pid文件 atexit.register(self.delpid) pid =
str(os.getpid())
file(self.pidfile,
'w+').write(
"%s\n" % pid)
def delpid(self): os.remove(self.pidfile)
def start(self):
""" Start the daemon """ # Check for a pidfile to see if the daemon already runs try: pf =
file(self.pidfile,
'r') pid =
int(pf.read().strip()) pf.close()
except IOError: pid =
None if pid: message =
"pidfile %s already exist. Daemon already running?\n" sys.stderr.write(message % self.pidfile) sys.exit(
1)
# Start the daemon self._daemonize() self._run()
def stop(self):
""" Stop the daemon """ # Get the pid from the pidfile try: pf =
file(self.pidfile,
'r') pid =
int(pf.read().strip()) pf.close()
except IOError: pid =
None if not pid: message =
"pidfile %s does not exist. Daemon not running?\n" sys.stderr.write(message % self.pidfile)
return # not an error in a restart # Try killing the daemon process try:
while 1: os.kill(pid, SIGTERM) time.sleep(
0.1)
except OSError, err: err =
str(err)
if err.find(
"No such process") >
0:
if os.path.exists(self.pidfile): os.remove(self.pidfile)
else:
print str(err) sys.exit(
1)
def restart(self):
""" Restart the daemon """ self.stop() self.start()
def _run(self):
""" You should override this method when you subclass Daemon. It will be called after the process has been daemonized by start() or restart(). """class MyDaemon(Daemon):
def _run(self):
while True: time.sleep(
1)
if __name__ ==
"__main__": daemon = MyDaemon(
'/tmp/daemon-example.pid')
if len(sys.argv) ==
2:
if 'start' == sys.argv[
1]: daemon.start()
elif 'stop' == sys.argv[
1]: daemon.stop()
elif 'restart' == sys.argv[
1]: daemon.restart()
else:
print "Unknown command" sys.exit(
2) sys.exit(
0)
else:
print "usage: %s start|stop|restart" % sys.argv[
0] sys.exit(
2)
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。