用Python监控、重启指定系统服务并发送通知邮件
作者:高玉涵
时间:2021.5.26 11:11
博客:blog.csdn.net/cg_i
背景
某一应用程序被部署在多台服务器上,近段时间程序会无规律的宕掉,有时一台、有时多台失效,机器其它应用均正常,重启失效应用后服务恢复正常。应用提供的服务需实时响应,加上部署机器较多,一时又无法定位故障成因,在没有找到解决办法之前,每当出现上述故障,首要任务是要及时发现、及时重启,以保证各项业务正常。应急用Python开发了一个监测记录应用状态的程序,当发现指定监控的应用失效,自动重启并通过邮件通知管理员,结合手机端邮件APP(这里用的是sina的)并打开通知功能,达到了及时提醒的目的。
Task Scheduler、launchd和cron
程序可在安装有Python3.4以上版本的任何机器上运行。如果你精通计算机,可能知道Windows上的Task Scheduler,OS X上的launchd,或Linux上的cron调试程序。这些工具文档齐全,而且可靠,它们都允许你安排程序在特定的时间启动(我设置为每5分钟检查一次)。
利用操作系统内置的调度程序,你不必自己写时钟代码来安排你的程序。
程序生成文件说明
monit.log日志格式及说明:
2021-05-26 10:33:52,252 File:"monit.py",line:82 INFO:启动:15688 xxxxx.exe C:\APP\xxxx\xxxxx.exe C:\Users\xxxx\xxxxxxx\monit running 2021-05-26 10:33:52
PID:15688
进程路径:C:\APP\xxxx\xxxxx.exe
进程工作路径:C:\Users\xxxx\xxxxxxx\monit
状态:running
创建时间:2021-05-26 10:33:52
邮件格式说明:
主题:发件人名,主机名,IP
monit.pyi源码
import socket
import logging
import psutil
import smtplib
import email.message
import email.policy
import email.utils
import time
from subprocess import PIPE
def sendmail(to, subject, content):
mail_host = "smtp.sohu.com" # SMTP服务器(这里用的是SOHU邮箱)
mail_user = "xxx" # 登录名
mail_pass = "XXXXXXXXXXX" # SMTP授权码
sender = 'XXX@sohu.com' # 寄件人
message = email.message.EmailMessage(email.policy.SMTP)
message['From'] = sender
message['To'] = to
message['Subject'] = subject
message['Date'] = email.utils.formatdate(localtime=True)
message['Message-ID'] = email.utils.make_msgid()
message.set_content(content)
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25) # 25为SMTP端口号
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, to, message.as_string())
except smtplib.SMTPException as e:
logging.error("{}\t{}".format('邮件发送失败:', str(e)))
raise
def get_host():
try:
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
return hostname, ip
except Exception:
raise
def ps(name):
pids = psutil.pids()
return [psutil.Process(pid) for pid in pids if psutil.Process(pid).name() == name]
if __name__ == "__main__":
try:
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s\tFile:\"%(filename)s\",line:%(lineno)s\t%(levelname)s:%(message)s',
filename='monit.log',
filemode='a')
content = ''
# 查找指定进程
proces = ps('XXXXXX.exe')
# 指定的进程不存在,启动程序
if len(proces) == 0:
p = psutil.Popen([r'C:\APP\XXXXXX\XXXXXX.exe'], stdout=PIPE)
timeAry = time.localtime(p.create_time())
otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeAry)
content = "启动:{} {} {} {} {} {}".format(p.pid, p.name(), p.exe(), p.cwd(), p.status(), otherStyleTime)
# 程序有多个实例时,登记并杀掉进程
elif len(proces) > 1:
for p in proces:
timeAry = time.localtime(p.create_time())
otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeAry)
content += "KILL:{} {} {} {} {} {}".format(p.pid, p.name(), p.exe(), p.cwd(), p.status(),
otherStyleTime)
p.kill()
p.wait(timeout=3)
if content:
logging.info(content)
(host, ip) = get_host()
subject = "{},{}".format(host, ip)
# 填入你实际的收件邮箱
sendmail('xxxx@sina.com', subject, content)
except Exception as e:
logging.error("{}".format(str(e)))