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"])