简介
项目中使用python写一个监控程序,每隔5秒监控目录,发现文件就立刻FTP同步到另一台服务器。业务要求高实时性和高可用性。为了谨防程序崩溃,特别编写一个守护进程程序,时刻监控程序是否崩溃并重新启动。
下面介绍两种实现方式。
第一种 监控进程PID方式
- Demo.py 10秒关闭程序,模拟程序崩溃
# -*- coding: utf-8 -*- import logging import time import os logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='e:/monitor/demo.log', filemode='a') # Demo.py 10秒关闭程序,模拟程序崩溃 # author 胖胖的alex 2017/09/10 class Demo: pidlogpath = "e:/monitor/pid.run" def __init__(self): pass def setpid(self): # 记录进程号PID fo = open(self.pidlogpath, "w") pid = str(os.getpid()) fo.write(pid) fo.flush() fo.close() return pid def execute(self): pid = self.setpid() logging.info("启动程序,进程号:" + str(pid)) i = 1 while True: logging.info("pid = " + pid + " ---------- run " + str(i) + " s ") time.sleep(1) i += 1 if i > 10: break logging.info("程序关闭...") if __name__ == '__main__': Demo().execute()
- e:/monitor/pid.run 储存Demo.py进程号
- MonitorPid.py 监控windows系统所有进程任务
定时任务执行,如果run.pid内进程号在系统中不存在,执行重启命令
# -*- coding: utf-8 -*- import psutil import os import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='e:/monitor/monitor.log', filemode='a') # PROCESS_RE = re.compile("pid=\d{1,4},\sname='\S{1,20}'") # 采用正则,获取数据 pid=x/xx/xxx/xxxx, name=[1~20个字符, # 监控windows系统所有进程服务任务。定时任务执行,发现run.pid进程号系统中不存在,执行命令python Demo.py启动程序 # author 胖胖的alex 2017/09/1 class Monitor: pidNotHandle = [] pidlogpath = "e:/monitor/pid.run" def __init__(self): self.pidNotHandle = list(psutil.process_iter()) # 获取当前计算机的pid def getpid(self): # 获取进程号PID fo = open(self.pidlogpath, "r") result = fo.read() fo.flush() fo.close() return result def execute(self): pid = [] for each in self.pidNotHandle: a = str(each) # each 是 class类型,可用type(each)查看类型 # a 数据样式为:psutil.Process(pid=0, name='System Idle Process') pid.append(a[15:-1]) # 只取括号内部分;pid=0, name='System Idle Process' status = 0 # 被监控程序进程存在状态,0不存在,1存在 for each in pid: nameposition = each.find("name") # 获取name的位置;name='System Idle Process' namevalue = each[nameposition + 6:-1] # 获取name值;System Idle Process pidposition = each.find("pid") pidvalue = each[pidposition + 4:nameposition-2] print("name="+namevalue + ", pid="+pidvalue+"\n") if pidvalue == self.getpid(): status = 1 print("发现进程==============name=" + namevalue + ", pid=" + pidvalue + "\n") break if status == 0: # 进程不存在,重新启动程序 cmd = "python Demo.py" os.popen(cmd) print("重启程序.............") print("ending.............") return 0 if __name__ == '__main__': Monitor().execute()
- pyInstaller 将MonitorPid.py程序生成monitor.exe文件
pyInstaller百度经验:http://jingyan.baidu.com/article/a378c960b47034b3282830bb.html
pyInstaller官方网站:http://www.pyinstaller.org/
执行命令
E:\mywork\python\workspace\monitor>pyinstaller -w MonitorPid.py 85 INFO: PyInstaller: 3.2.1 85 INFO: Python: 3.5.4 85 INFO: Platform: Windows-10-10.0.15063-SP0 86 INFO: wrote E:\mywork\python\workspace\monitor\MonitorPid.spec 87 INFO: UPX is not available. 88 INFO: Extending PYTHONPATH with paths ['E:\\mywork\\python\\workspace\\monitor', 'E:\\mywork\\python\\workspace\\monitor'] 88 INFO: checking Analysis 102 INFO: checking PYZ 113 INFO: checking PKG 115 INFO: Building because toc changed 115 INFO: Building PKG (CArchive) out00-PKG.pkg 133 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully. 137 INFO: Bootloader e:\mywork\python\soft\python35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe 137 INFO: checking EXE 137 INFO: Building because name changed 137 INFO: Building EXE from out00-EXE.toc 138 INFO: Appending archive to EXE E:\mywork\python\workspace\monitor\build\MonitorPid\MonitorPid.exe 141 INFO: Building EXE from out00-EXE.toc completed successfully. 144 INFO: checking COLLECT 145 INFO: Building COLLECT out00-COLLECT.toc 388 INFO: Building COLLECT out00-COLLECT.toc completed successfully.
打包成功,杀毒软件会报警,选择找回文件或添加信任,下图是打包后程序
- 设置MonitorPid.exe到windows计划任务
windows设置计划任务百度经验教程:http://jingyan.baidu.com/article/ca00d56c767cfae99febcf73.html
贴出核心配置截图:
第二种监控进程名方式
- 同第一种方式的第一步
- pyInstaller 将Demo.py打包成DemoServer.exe
Python程序获取进程名称,最直接办法是打包成exe文件
E:\mywork\python\workspace\monitor>pyinstaller -w DemoServer.py
87 INFO: PyInstaller: 3.2.1
90 INFO: Python: 3.5.4
90 INFO: Platform: Windows-10-10.0.15063-SP0
93 INFO: wrote E:\mywork\python\workspace\monitor\DemoServer.spec
99 INFO: UPX is not available.
101 INFO: Extending PYTHONPATH with paths
['E:\\mywork\\python\\workspace\\monitor',
'E:\\mywork\\python\\workspace\\monitor']
101 INFO: checking Analysis
101 INFO: Building Analysis because out00-Analysis.toc is non existent
102 INFO: Initializing module dependency graph...
103 INFO: Initializing module graph hooks...
104 INFO: Analyzing base_library.zip ...
2195 INFO: running Analysis out00-Analysis.toc
2196 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
required by e:\mywork\python\soft\python35\python.exe
2595 INFO: Caching module hooks...
2598 INFO: Analyzing E:\mywork\python\workspace\monitor\DemoServer.py
2825 INFO: Loading module hooks...
2826 INFO: Loading module hook "hook-encodings.py"...
2912 INFO: Loading module hook "hook-xml.py"...
3057 INFO: Loading module hook "hook-pywintypes.py"...
3288 INFO: Loading module hook "hook-pydoc.py"...
3304 INFO: Looking for ctypes DLLs
3304 INFO: Analyzing run-time hooks ...
3310 INFO: Looking for dynamic libraries
3556 INFO: Looking for eggs
3556 INFO: Using Python library e:\mywork\python\soft\python35\python35.dll
3556 INFO: Found binding redirects:
[]
3560 INFO: Warnings written to E:\mywork\python\workspace\monitor\build\DemoServer\warnDemoServer.txt
3568 INFO: checking PYZ
3568 INFO: Building PYZ because out00-PYZ.toc is non existent
3568 INFO: Building PYZ (ZlibArchive) E:\mywork\python\workspace\monitor\build\DemoServer\out00-PYZ.pyz
3993 INFO: Building PYZ (ZlibArchive) E:\mywork\python\workspace\monitor\build\DemoServer\out00-PYZ.pyz completed successfully.
4009 INFO: checking PKG
4011 INFO: Building PKG because out00-PKG.toc is non existent
4012 INFO: Building PKG (CArchive) out00-PKG.pkg
4025 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
4028 INFO: Bootloader e:\mywork\python\soft\python35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe
4028 INFO: checking EXE
4028 INFO: Building EXE because out00-EXE.toc is non existent
4028 INFO: Building EXE from out00-EXE.toc
4029 INFO: Appending archive to EXE E:\mywork\python\workspace\monitor\build\DemoServer\DemoServer.exe
4031 INFO: Building EXE from out00-EXE.toc completed successfully.
4036 INFO: checking COLLECT
4036 INFO: Building COLLECT because out00-COLLECT.toc is non existent
4039 INFO: Building COLLECT out00-COLLECT.toc
4378 INFO: Building COLLECT out00-COLLECT.toc completed successfully.
- MonitorPidServer.py 程序
监控系统所有进程名称,如果没有DemoServer.exe进程名称,执行命令DemoServer.exe
# -*- coding: utf-8 -*-
import psutil
import os
import logging
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='e:/monitor/monitor.log',
filemode='a')
# PROCESS_RE = re.compile("pid=\d{1,4},\sname='\S{1,20}'") # 采用正则,获取数据 pid=x/xx/xxx/xxxx, name=[1~20个字符,
# 监控windows系统所有进程服务任务。定时任务执行,发现run.pid进程号系统中不存在,执行命令python Demo.py启动程序
# author 胖胖的alex 2017/09/1
class MonitorServer:
pidNotHandle = []
servername = "DemoServer.exe"
def __init__(self):
self.pidNotHandle = list(psutil.process_iter()) # 获取当前计算机的pid
def execute(self):
pid = []
for each in self.pidNotHandle:
a = str(each) # each 是 class类型,可用type(each)查看类型
# a 数据样式为:psutil.Process(pid=0, name='System Idle Process')
pid.append(a[15:-1]) # 只取括号内部分;pid=0, name='System Idle Process'
status = 0 # 被监控程序进程存在状态,0不存在,1存在
for each in pid:
nameposition = each.find("name") # 获取name的位置;name='System Idle Process'
namevalue = each[nameposition + 6:-1] # 获取name值;System Idle Process
pidposition = each.find("pid")
pidvalue = each[pidposition + 4:nameposition-2]
print("name="+namevalue + ", pid="+pidvalue+"\n")
if namevalue == self.servername:
status = 1
print("发现进程==============name=" + namevalue + ", pid=" + pidvalue + "\n")
break
if status == 0: # 进程不存在,重新启动程序
cmd = "E:/mywork/python/workspace/monitor/dist/DemoServer/" + self.servername
os.popen(cmd)
print("重启程序.............")
print("ending.............")
return 0
if __name__ == '__main__':
MonitorServer().execute()
- 同第一种方式的第四步
- 同第一种方式的第五步