python 监控服务端口并发送钉钉和邮件v1.0

python 监控服务端口并发送钉钉和邮件v1.0

基本逻辑

  • 把ip+ports定义到json文件
  • 加载json文件
  • 循环json文件里面定义的多主机端口
  • 开启socket线程监测端口是否监听
  • 异常时直接通知钉钉同时把异常ip+port写入文件
  • 邮件附件发送异常文件

说明

本脚本只是能监测服务端口是否开启,无法监测服务是否健康。只能做个简单的监控。

文件目录介绍

目录/opt/tools/monitoring/
[root@localhost rc]# tree -L 1
.
├── crontab.sh #定时任务脚本
├── ip_port.json # 定义主机和端口(多台服务器)
├── jk002.py #python 脚本
└── temp  # 异常端口和ip写入temp目录下的文件,邮件附件发送

1 directory, 3 files
[root@localhost rc]# 

crontab.sh 源码

#!/bin/bash

cd  /opt/tools/monitoring/
python jk002.py

ip_ports.json 文件定义

{
    "rlszw_dev": {
        "10.21.22.102": {
            "ssh": 22,
            "mysql": 3306,
            "show": 8099,
            "appInterface": 8098,
            "mis": 8097,
            "ass": 8096,
            "share": 8095,
            "ddm": 8094,
            "dctrl": 8093,
            "cas_server": 8092,
            "integration": 8091,
            "lszw_nginx": 8180,
            "cas_nginx": 8181,
            "dcmqttd": 18700,
            "acadgrpc": 18600
        }
    }

jk002.py源码

# -*- coding:utf8 -*-


import socket
import time
import os
import thread
import json
import urllib2
import sys
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
reload(sys)
sys.setdefaultencoding('utf-8')
socket.setdefaulttimeout(1)

date = time.strftime("%Y%d%m%H%M")
file = './temp/'+date+'result.'+'txt'


def dingding(tokenid, subject, message):
    url = "https://oapi.dingtalk.com/robot/send?access_token=" + tokenid
    header = {
        "Content-Type": "application/json",
        "charset": "utf-8"
    }
    data = {
        "msgtype": "text",
        "text": {
            "content": subject + '\n' + message
        },
        "at": {
            "atMobiles": [
                "1518*****"
                # "1352*****"
                # "1519*****",
                # "1510*****",
                # "1833*****"
            ],
            "isAtAll": False
        }
    }
    sendData = json.dumps(data)
    request = urllib2.Request(url, data=sendData, headers=header)
    urlopen = urllib2.urlopen(request)
    return urlopen.read()


def socket_port(ip, port):
    """
    输入IP和端口号,扫描判断端口是否开放
    """

    try:

        if port >= 65535:
            print u'端口扫描结束'
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = s.connect_ex((ip, port))
        message = str(port)
        if result == 0:
            lock.acquire()
            print ip, u':', port, u'端口开放'
            # write_result(ip.encode("utf-8")+':'+message+'端口开放')
            lock.release()
        else:
            lock.acquire()
            print ip, u':', port, u'端口异常,开始发送钉钉通知'
            tokenid = "************" #钉钉机器人tokenid 
            subject = ip.encode('utf-8')+'主机'
            message = str(port).encode('utf-8')+'端口异常'
            dingding(tokenid, subject, message)
            write_result(ip.encode("utf-8")+':'+message+'端口异常')
            lock.release()

        s.close()
    except Exception, e:
        print str(e)


def ip_scan(ip, ports):
    """
    输入IP,扫描IP的0-65534端口情况
    """
    try:
        print u'开始扫描 %s' % ip
        start_time = time.time()
        for i in ports:
            # print i
            # print type(i)
            thread.start_new_thread(socket_port, (ip, i))
            time.sleep(2)
        print u'扫描端口完成,总共用时 :%.2f' % (time.time() - start_time)
        # raw_input("Press Enter to Exit")
    except Exception, e:
        print str(e)


def send_mail():
    # 第三方 SMTP 服务
    mail_host = "smtp.163.com"  # 设置服务器
    mail_user = "******@163.com"  # 用户名
    mail_pass = "**********"  # 口令

    sender = '*************@163.com'
    receivers = ['********@qq.com','*******@qq.com']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
    message = MIMEMultipart()
    # message = MIMEText('我们的工作基本一致', 'plain', 'utf-8')
    message.attach(MIMEText('服务端口监控', 'plain', 'utf-8'))
    message['From'] = sender
    message['To'] = ','.join(receivers)
    subject = '服务端口监控'
    message['Subject'] = Header(subject, 'utf-8')
    # 附件
    # 构造附件1,传送当前目录下的 test.txt 文件
    att1 = MIMEText(open(file, 'rb').read(), 'base64', 'utf-8')
    att1["Content-Type"] = 'application/octet-stream'
    # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
    att1["Content-Disposition"] = 'attachment; filename="result.txt"'
    message.attach(att1)

    # # 构造附件2,传送当前目录下的 runoob.txt 文件
    # att2 = MIMEText(open('runoob.txt', 'rb').read(), 'base64', 'utf-8')
    # att2["Content-Type"] = 'application/octet-stream'
    # att2["Content-Disposition"] = 'attachment; filename="runoob.txt"'
    # message.attach(att2)

    try:
        smtpObj = smtplib.SMTP()
        smtpObj.connect(mail_host, 25)    # 25 为 SMTP 端口号
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print "邮件发送成功"
    except Exception, e:
        print str(e)


def write_result(result):

    # print file
    with open(file, 'a') as f:
        f.write(result+'\n')


if __name__ == '__main__':
    # url = raw_input('Input the ip you want to scan:\n')
    lock = thread.allocate_lock()
    # port = [3389, 22, 43, 135, 137]
    # ip = "127.0.0.1"
    with open("./ip_port.json", 'r') as f:
        data = json.load(f)

    for env_key in data:
        for ip_key in data[env_key]:
            ip = ip_key
            ports = data[env_key][ip_key]
            key_list = list(ports.keys())
            val_list = list(ports.values())
            ip_scan(ip, val_list)
    if os.path.exists(file):
        send_mail()


#

维护定时任务

crontab -e
输入 0 */1 * * * sh /opt/monitoring/crontab.sh

阿里云ecs服务器需要修改mail发送端口为ssl类型

采用vpc网络时,默认防火墙禁止25端口通信

    try:
        # smtpObj = smtplib.SMTP()
        smtpObj=smtplib.SMTP_SSL(mail_host, 994)
        # smtpObj.connect(mail_host, 25)    # 25 为 SMTP 端口号
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print "邮件发送成功"
        smtpObj.quit()
    except Exception, e:
        print "邮件发送失败"
        print str(e)

你可能感兴趣的:(python 监控服务端口并发送钉钉和邮件v1.0)