python实现守护进程_python中的daemon守护进程实现方法

#!/usr/bin/env python

#encoding: utf-8#description: 一个守护进程的简单包装类, 具备常用的start|stop|restart|status功能, 使用方便

# 需要改造为守护进程的程序只需要重写基类的run函数就可以了

#date:2015-10-29#usage: 启动: python daemon_class.py start

# 关闭: python daemon_class.py stop

# 状态: python daemon_class.py status

# 重启: python daemon_class.py restart

# 查看: ps-axj |grep daemon_class

import atexit, os, sys, time, signalclassCDaemon:''' a generic daemon class.

usage: subclass the CDaemonclass and overridethe 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=True

def daemonize(self):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.chdir(self.home_dir)

os.setsid()

os.umask(self.umask)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+')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())

def sig_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)

def get_pid(self):try:

pf= file(self.pidfile, 'r')

pid= int(pf.read().strip())

pf.close()

except IOError:

pid=None

except SystemExit:

pid=Nonereturnpid

def del_pid(self):ifos.path.exists(self.pidfile):

os.remove(self.pidfile)

def start(self,*args, **kwargs):if self.verbose >= 1:

print'ready to starting ......'#checkfor a pid file to see ifthe 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(1)

#start the daemon

self.daemonize()

self.run(*args, **kwargs)

def stop(self):if self.verbose >= 1:

print'stopping ...'pid=self.get_pid()ifnot pid:

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#tryto kill the daemon processtry:

i= 0

while 1:

os.kill(pid, signal.SIGTERM)

time.sleep(0.1)

i= i + 1

if i % 10 == 0:

os.kill(pid, signal.SIGHUP)

except OSError, err:

err=str(err)if err.find('No such process') > 0:ifos.path.exists(self.pidfile):

os.remove(self.pidfile)else:

print str(err)

sys.exit(1)if self.verbose >= 1:

print'Stopped!'def restart(self,*args, **kwargs):

self.stop()

self.start(*args, **kwargs)

def is_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()'

classClientDaemon(CDaemon):

def __init__(self, name, save_path, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull, home_dir='.', umask=022, verbose=1):

CDaemon.__init__(self, save_path, stdin, stdout, stderr, home_dir, umask, verbose)

self.name=name #派生守护进程类的名称

def run(self, output_fn,**kwargs):

fd= open(output_fn, 'w')whileTrue:

line= time.ctime() + '\n'fd.write(line)

fd.flush()

time.sleep(1)

fd.close()if __name__ == '__main__':

help_msg= 'Usage: python %s ' % sys.argv[0]if len(sys.argv) != 2:

print help_msg

sys.exit(1)

p_name= 'clientd'#守护进程名称

pid_fn= '/tmp/daemon_class.pid'#守护进程pid文件的绝对路径

log_fn= '/tmp/daemon_class.log'#守护进程日志文件的绝对路径

err_fn= '/tmp/daemon_class.err.log'#守护进程启动过程中的错误日志,内部出错能从这里看到

cD= ClientDaemon(p_name, pid_fn, stderr=err_fn, verbose=1)if sys.argv[1] == 'start':

cD.start(log_fn)

elif sys.argv[1] == 'stop':

cD.stop()

elif sys.argv[1] == 'restart':

cD.restart(log_fn)

elif sys.argv[1] == 'status':

alive=cD.is_running()ifalive:

print'process [%s] is running ......' %cD.get_pid()else:

print'daemon process [%s] stopped' %cD.nameelse:

print'invalid argument!'print help_msg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值