起因:
自己的MC服务器需要一个监控告警的小脚本
优化:
以后优化一下,用阿里云服务进行部署
代码实现:
# !/usr/bin/python3
# -*- coding=utf-8 -*-
# @Author : 世界
# @file: PortMonitor.py
# @time: 2020-12-30 12:27:02
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import time
import smtplib
import email
import socket
import logging
# 使用socket获取端口状态
def get_ip_status(server_ip, port):
# 创建一个名为sk的socket连接
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# socket超时时间3秒
sk.settimeout(3)
try:
# 尝试connect 服务的端口, 若成功则返回 True
sk.connect((server_ip, port))
return True
except Exception:
# 若是不成功或其他错误,都返回 False
return False
# 最后一定要记得结束掉socket,,否则会占用大量资源导致系统宕机
sk.close()
# 邮件发送模块
# 这里设置你自己的邮件服务信息
def smtp_sendmail(Subj, Main_Body, To):
mailserver = 'smxxtp.mxxxhichina.com'
username = 'system@xxx.top'
password = '123456'
From = 'system@xxx.top'
Tos = To.split(';')
Date = email.utils.formatdate()
msg = MIMEMultipart()
msg["Subject"] = Subj
msg["From"] = From
msg["To"] = To
msg["Date"] = Date
part = MIMEText(Main_Body)
msg.attach(part)
server = smtplib.SMTP_SSL(mailserver, 465)
server.login(username, password)
failed = server.sendmail(From, Tos, msg.as_string())
server.quit()
if failed:
print('Email sending failed ! The error message is as follows: ', failed)
return 0 # 判断邮件发送状态,失败则返回0
else:
print('Email sent successfully ! ')
return 1 # 成功则返回1
# 监控函数
def main():
cu_time = time.asctime()
host = '13.15.1.12'
port = 9898
second = 300 # 每300秒检查一次端口是否开放
recipients = 'nxx@123.com' # 收件人email地址
logname = 'PortMonitoring.log' # # logging日志记录
# logging 输出样式为 时间--告警等级--会话信息; error以下的info等信息不会显示在stdout上面
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
# 格式化以下logging里面的时间显示格式
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
# logging 初始化
logging.basicConfig(filename=logname, level=logging.DEBUG, format=LOG_FORMAT, datefmt=DATE_FORMAT)
i_close = 0 # 端口关闭时邮件发送的次数累加器, 目前仅允许状态close时发送一次邮件
i_open = 0 # 端口开启时邮件发送的次数累加器, 目前仅允许状态close时发送一次邮件
while True:
# 加入了仅在接口状态第一次Up Down改变时,自动发送邮件
try:
res = get_ip_status(host, port) # 获取端口状态信息
if int(res) == 0:
# stdout打印下信息
print('{2} >>> Error ! {0} port {1} is not open !'.format(host, port, cu_time))
# logging 记录当前端口关闭信息
logging.error('Error >>> {0} port {1} is not open !'.format(host, port))
time.sleep(1) # 间隔一秒钟
reconfirm = get_ip_status(host, port) # 再次获取端口的状态信息是否时close状态,
if int(res) == 0 and reconfirm == 0 and i_close < 1: # 再次获得的
Subj = 'Error! {0} port {1} is not open ! Time: {2}'.format(host, port, cu_time)
Main_Body = ''
To = recipients
# 发送告警邮件
smtp_sendmail(Subj, Main_Body, To)
i_close += 1 # 邮件发送后,将close计数器+1,配合前面的的if i_close < 1 可以仅发送第一次端口状态变化邮件
i_open = 0 # 将open的计数器 置0, 这样端口恢复正常后会执行elif int(res) == 1后面的代码,从而发送状态变法邮件
logging.error('Info >>> {0} port {1} is not open ! Email has been sent ! '.format(host, port))
time.sleep(second) # 执行一次后 休眠300秒
elif int(res) == 1:
print('{0} port {1} is open !'.format(host, port))
logging.info('{0} port {1} is open !'.format(host, port))
if i_open < 1:
Subj = 'Info! {0} port {1} is open ! Time: {2}'.format(host, port, cu_time)
Main_Body = ''
To = recipients
smtp_sendmail(Subj, Main_Body, To)
logging.error('Info >>> {0} port {1} is open ! Email has been sent ! '.format(host, port))
i_open += 1 # 邮件发送后,将open计数器+1,配合前面的的 if i_open < 1 可以仅发送第一次端口状态变化邮件
i_close = 0 # 将close的计数器 置0, 这样端口恢复正常后会执行if int(res) == 1后面的代码,从而发送状态变法邮件
time.sleep(second)
except Exception as e:
# 异常日志 仅记录,不发送告警邮件
print('Critica >>> An unexpected error occurred ! >>> Detail: {}'.format(e))
logging.critical('An exception occurred while checking the port ! >>> Detail: {}'.format(e))
# Subj = 'Port Exception Error !'
# Main_Body = '''
# Port Exception Error !\n\n\n
# {}\n\n
# {}
# '''.format(e, cu_time)
# To = recipients
# smtp_sendmail(Subj, Main_Body, To)
if __name__ == '__main__':
# check_result = get_ip_status('139.155.91.142', 9898)
# print(check_result[1])
# 其实目前版本有一个bug ,在端口剧烈up down的时候无法自动识别,此时会频繁发送告警邮件
main()