Python写的服务监控程序实例
前言:
Redhat下安装Python2.7
rhel6.4自带的是2.6,发现有的机器是python2.4。到python网站下载源代码,解压到Redhat上,然后运行下面的命令:
#./configure--prefix=/usr/local/python27 #make #makeinstall
这样安装之后默认不会启用Python2.7,需要使用/usr/local/python27/bin/python2.7调用新版本的python。
而下面的安装方式会直接接管现有的python
#./configure #make #makeinstall
开始:
服务子进程被监控主进程创建并监控,当子进程异常关闭,主进程可以再次启动之。使用了python的subprocess模块。就这个简单的代码,居然互联网上没有现成可用的例子。没办法,我写好了贡献出来吧。
首先是主进程代码:service_mgr.py
#!/usr/bin/python #-*-coding:UTF-8-*- #cheungmine #stdin、stdout和stderr分别表示子程序的标准输入、标准输出和标准错误。 # #可选的值有: # subprocess.PIPE-表示需要创建一个新的管道. # 一个有效的文件描述符(其实是个正整数) # 一个文件对象 # None-不会做任何重定向工作,子进程的文件描述符会继承父进程的. # #stderr的值还可以是STDOUT,表示子进程的标准错误也输出到标准输出. # #subprocess.PIPE #一个可以被用于Popen的stdin、stdout和stderr3个参数的特输值,表示需要创建一个新的管道. # #subprocess.STDOUT #一个可以被用于Popen的stderr参数的特输值,表示子程序的标准错误汇合到标准输出. ################################################################################ importos importsys importgetopt importtime importdatetime importcodecs importoptparse importConfigParser importsignal importsubprocess importselect #logging #requirepython2.6.6andlater importlogging fromlogging.handlersimportRotatingFileHandler ##logsettings:SHOULDBECONFIGUREDBYconfig LOG_PATH_FILE="./my_service_mgr.log" LOG_MODE='a' LOG_MAX_SIZE=4*1024*1024#4Mperfile LOG_MAX_FILES=4 #4Files:my_service_mgr.log.1,printmy_service_mgrlog.2,... LOG_LEVEL=logging.DEBUG LOG_FORMAT="%(asctime)s%(levelname)-10s[%(filename)s:%(lineno)d(%(funcName)s)]%(message)s" handler=RotatingFileHandler(LOG_PATH_FILE,LOG_MODE,LOG_MAX_SIZE,LOG_MAX_FILES) formatter=logging.Formatter(LOG_FORMAT) handler.setFormatter(formatter) Logger=logging.getLogger() Logger.setLevel(LOG_LEVEL) Logger.addHandler(handler) #coloroutput # pid=os.getpid() defprint_error(s): print'\033[31m[%d:ERROR]%s\033[31;m'%(pid,s) defprint_info(s): print'\033[32m[%d:INFO]%s\033[32;m'%(pid,s) defprint_warning(s): print'\033[33m[%d:WARNING]%s\033[33;m'%(pid,s) defstart_child_proc(command,merged): try: ifcommandisNone: raiseOSError,"Invalidcommand" child=None ifmergedisTrue: #mergestdoutandstderr child=subprocess.Popen(command, stderr=subprocess.STDOUT,#表示子进程的标准错误也输出到标准输出 stdout=subprocess.PIPE #表示需要创建一个新的管道 ) else: #DONOTmergestdoutandstderr child=subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE) returnchild exceptsubprocess.CalledProcessError: pass#handleerrorsinthecalledexecutable exceptOSError: pass#executablenotfound raiseOSError,"Failedtoruncommand!" defrun_forever(command): print_info("startchildprocesswithcommand:"+''.join(command)) Logger.info("startchildprocesswithcommand:"+''.join(command)) merged=False child=start_child_proc(command,merged) line='' errln='' failover=0 whileTrue: whilechild.poll()!=None: failover=failover+1 print_warning("childprocessshutdownwithreturncode:"+str(child.returncode)) Logger.critical("childprocessshutdownwithreturncode:"+str(child.returncode)) print_warning("restartchildprocessagain,times=%d"%failover) Logger.info("restartchildprocessagain,times=%d"%failover) child=start_child_proc(command,merged) #readchildprocessstdoutandlogit ch=child.stdout.read(1) ifch!=''andch!='\n': line+=ch ifch=='\n': print_info(line) line='' ifmergedisnotTrue: #readchildprocessstderrandlogit ch=child.stderr.read(1) ifch!=''andch!='\n': errln+=ch ifch=='\n': Logger.info(errln) print_error(errln) errln='' Logger.exception("!!!shouldneverruntothis!!!") if__name__=="__main__": run_forever(["python","./testpipe.py"])
然后是子进程代码:testpipe.py
#!/usr/bin/python #-*-coding:UTF-8-*- #cheungmine #模拟一个woker进程,10秒挂掉 importos importsys importtime importrandom cnt=10 whilecnt>=0: time.sleep(0.5) sys.stdout.write("OUT:%s\n"%str(random.randint(1,100000))) sys.stdout.flush() time.sleep(0.5) sys.stderr.write("ERR:%s\n"%str(random.randint(1,100000))) sys.stderr.flush() #printstr(cnt) #sys.stdout.flush() cnt=cnt-1 sys.exit(-1)
Linux上运行很简单:
$pythonservice_mgr.py
Windows上以后台进程运行:
>startpythonwservice_mgr.py
代码中需要修改:
run_forever(["python","testpipe.py"])