classCDaemon(object):"""a generic daemon class.
usage: subclass the CDaemon class and override the run() method
stderr 表示错误日志文件绝对路径, 收集启动过程中的错误日志
verbose 表示将启动运行过程中的异常错误信息打印到终端,便于调试,建议非调试模式下关闭, 默认为1, 表示开启
save_path 表示守护进程pid文件的绝对路径"""
def __init__(self, save_path, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull, home_dir='.', umask=022, verbose=1):
self.stdin=stdin
self.stdout=stdout
self.stderr=stderr
self.pidfile= save_path #pid文件绝对路径
self.home_dir =home_dir
self.verbose= verbose #调试开关
self.umask =umask
self.daemon_alive=Truedefdaemonize(self):try:
pid=os.fork()if pid >0:
sys.exit(0)exceptOSError, e:
sys.stderr.write('fork #1 failed: %d (%s)\n' %(e.errno, e.strerror))
sys.exit(1)
os.chdir(self.home_dir)
os.setsid()
os.umask(self.umask)try:
pid=os.fork()if pid >0:
sys.exit(0)exceptOSError, 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+')ifself.stderr:
se= file(self.stderr, 'a+', 0)else:
se=so
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())defsig_handler(signum, frame):
self.daemon_alive=False
signal.signal(signal.SIGTERM, sig_handler)
signal.signal(signal.SIGINT, sig_handler)if self.verbose >= 1:print 'daemon process started ...'atexit.register(self.del_pid)
pid=str(os.getpid())
file(self.pidfile,'w+').write('%s\n' %pid)defget_pid(self):try:
pf= file(self.pidfile, 'r')
pid=int(pf.read().strip())
pf.close()exceptIOError:
pid=NoneexceptSystemExit:
pid=Nonereturnpiddefdel_pid(self):ifos.path.exists(self.pidfile):
os.remove(self.pidfile)def start(self, *args, **kwargs):if self.verbose >= 1:print 'ready to starting ......'
#check for a pid file to see if the daemon already runs
pid =self.get_pid()ifpid:
msg= 'pid file %s already exists, is it already running?\n'sys.stderr.write(msg%self.pidfile)
sys.exit(0)#start the daemon
self.daemonize()
self.run(*args, **kwargs)defstop(self):if self.verbose >= 1:print 'stopping ...'pid=self.get_pid()if notpid:
msg= 'pid file [%s] does not exist. Not running?\n' %self.pidfile
sys.stderr.write(msg)ifos.path.exists(self.pidfile):
os.remove(self.pidfile)return
#try to kill the daemon process
try:
i=0while 1:
os.kill(pid, signal.SIGTERM)
time.sleep(0.1)
i= i + 1
if i % 10 ==0:
os.kill(pid, signal.SIGHUP)exceptOSError, err:
err=str(err)if err.find('No such process') >0:ifos.path.exists(self.pidfile):
os.remove(self.pidfile)else:printstr(err)
sys.exit(1)if self.verbose >= 1:print 'Stopped!'
def restart(self, *args, **kwargs):
self.stop()
self.start(*args, **kwargs)defis_running(self):
pid=self.get_pid()#print(pid)
return pid and os.path.exists('/proc/%d' %pid)def run(self, *args, **kwargs):#NOTE: override the method in subclass
print 'base class run()'