python实现自动化之路(自动巡检服务器告警)

前言

需求介绍:设计需求:一到周末,公司总是会让我们人肉监控服务器状态(因为技术还没到互联网层公司的技术,没有自动化—例如工具Ansible之类的,ε=(´ο`*)))唉) 所以,我觉得这种东西如果可以实现一个远程自动化的监控工具是再好不过了,周末可以省下大把时间去浪~

劳资周末就要出去浪!

《python实现自动化之路(自动巡检服务器告警)》

当然本项目也可以作为一个python练手的小项目哟!

《python实现自动化之路(自动巡检服务器告警)》
以下正文

Environment(环境)

本项目为python编写的项目。

  • python3.6+

用到的库:

  • paramiko (linux ssh库)
  • smtplib (邮件库)
  • APScheduler (定时任务库)

项目目录结构

monitor-linux()

|--config
    |--gol.py               (全局变量字典)
    |--init_configs.py      (读取ini初始化配置)
    |--linux_config.ini     (linux服务器配置文件)
    |--mail_settings.ini    (邮箱设置配置文件)
    |--time_config.ini      (cron定时设置配置文件)
|--mail
    |--send_mails.py        (发送邮件)
|--monitor
    |--monitor.py           (监控linux模块,连接linux服务器)
|--utils
    |--util.py              (工具类)
|--run.py                   (程序入口)

主要模块介绍

run .py (程序入口)

先从程序入口介绍!代码如下:

# coding = utf-8

""" @author: sy @file: run.py @time: 2018/9/23 18:11 @desc: 程序入口,定时任务 """

import sys, os

from config import gol

BASE_DIR = os.path.dirname((os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

from monitor.monitor import Monitor
from mail.send_mails import SendMail
from config.init_configs import init_config, get_linux_config
from apscheduler.schedulers.blocking import BlockingScheduler


def auto_job():
    linux_dict = get_linux_config()
    content_list = []
    """ [(10.10.111.1,cd $(locate taskmngdomain1/nohuplogs) ; tail -50 *log*`date +%F`*), (10.10.111.2,cd $(locate taskmngdomain2/nohuplogs) ; tail -50 *log*`date +%F`*)]"""
    cmd_list = gol.get_value('cmd_list')
    for ip in linux_dict:
        linux_info = linux_dict[ip].split(',')  # 根据ip获取user和pwd,通过逗号分隔成list(linux_info--> [user,pwd])
        user = linux_info[0]
        pwd = linux_info[1]
        monitor = Monitor(ip, user, pwd)
        # cmd的获取,添加根据ini不同ip实现动态对应linux指令
        for cmd_tuple in cmd_list:
            if cmd_tuple[0] == ip:
                cmd = cmd_tuple[1]  # 将指令赋予cmd
                break  # 若找到了,则不浪费循环资源直接跳出
        content = f'当前服务器ip:{ip},日志内容:
' + monitor.link_server(cmd) + '

'
        content_list.append(content)
    sendMail = SendMail()
    sendMail.send_mails(''.join(content_list))
    sendMail.mail_close()   #关闭连接


def main():
    init_config()  # 初始化配置
    """ 基于quartz的定时任务调度器 """
    scheduler = BlockingScheduler()
    """ FIELD_NAMES = ('year', 'month', 'day', 'week', 'day_of_week', 'hour', 'minute', 'second') 没用过quartz的同学去了解下CRON表达式~文档如下: https://apscheduler.readthedocs.io/en/stable/modules/triggers/cron.html#module-apscheduler.triggers.cron """
    year = str(gol.get_value('year') or None)
    month = str(gol.get_value('month') or None)
    day = str(gol.get_value('day') or None)
    week = str(gol.get_value('week') or None)
    day_of_week = str(gol.get_value('day_of_week') or None)
    hour = str(gol.get_value('hour') or None)
    minute = str(gol.get_value('minute') or None)
    second = str(gol.get_value('second') or None)
    scheduler.add_job(auto_job, 'cron', year=year, month=month, day=day,
                      week=week, day_of_week=day_of_week, hour=hour, minute=minute, second=second, id='auto_job_id')
    try:
        print('程序开始!-------->Job running(Tips: Ctrl + c 终止程序)')
        scheduler.start()
    except (KeyboardInterrupt, SystemExit):
        print('退出程序!')
        scheduler.remove_job('auto_job_id')


if __name__ == '__main__':
    main()
    # auto_job()

这部分主要是程序入口,首先在main方法中对配置文件内容进行初始化加载,将各种变量参数加载到程序中,其次写了一个job方法,此方法中实现了程序逻辑主流程,从读取用户配置的相关linux服务器、邮箱以及linux命令信息,连接到服务,并将linux远程执行后得到的结果以邮件的形式发送。最后通过apscheduler第三方库来实现CRON的定时调用job功能…!

monitor .py (监控linux模块,连接linux服务器)

# coding = utf-8

""" @author: sy @file: monitor.py @time: 2018/9/22 15:33 @desc: 远程连接linux ssh监控后台日志 """
import paramiko


class Monitor(object):
    def __init__(self, server_ip, user, pwd):
        """ 初始化ssh客户端 """
        try:
            client = paramiko.SSHClient()
            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.client = client
            print('------------开始连接服务器(%s)-----------' % server_ip)
            self.client.connect(server_ip, 22, username=user, password=pwd, timeout=4)
            print('------------认证成功!.....-----------')
        except Exception:
            print(f'连接远程linux服务器(ip:{server_ip})发生异常!请检查用户名和密码是否正确!')

    def link_server(self, cmd):
        """连接服务器发送命令"""
        try:
            stdin, stdout, stderr = self.client.exec_command(cmd)
            content = stdout.read().decode('gbk')
            return content
        except Exception as e:
            print('link_server-->返回命令发生异常,内容:', e)
        finally:
            self.client.close()


if __name__ == '__main__':
    pass

此模块使用了第三库 paramiko .py,进行远程连接,将所配置的命令发给linux,随后将linux相应返回!

send_mails .py (发送邮件)

# coding = utf-8

""" @author: sy @file: send_mails.py @time: 2018/9/22 16:55 @desc: 发送邮件模块 """

import smtplib
from email.header import Header
from email.mime.text import MIMEText

from config import gol


class SendMail(object):
    def __init__(self):
        """ 初始化邮箱模块 """
        try:
            self.mail_host = gol.get_value("mail_host")  # 邮箱服务器
            self.mail_port = gol.get_value("mail_port")  # 邮箱服务端端口
            self.mail_user = gol.get_value("mail_user")  # 邮箱用户名
            self.mail_pwd = gol.get_value("mail_pwd")  # 邮箱密码
            self.mail_receivers = gol.get_value("mail_receivers").split(',')  # 收件人,以逗号分隔成列表
            smtp = smtplib.SMTP()
            smtp.connect(self.mail_host, self.mail_port)
            smtp.login(self.mail_user, self.mail_pwd)
            self.smtp = smtp
        except:
            print('发邮件---->初始化失败!请检查用户名和密码是否正确!')

    def send_mails(self, content):
        """ 发送邮件 """
        try:
            message = MIMEText(content, 'plain', 'utf-8')
            message['From'] = Header("巡检机器人小咪", 'utf-8')
            message['To'] = Header("系统警告", 'utf-8')
            subject = '各系统巡检信息'
            message['Subject'] = Header(subject, 'utf-8')
            self.smtp.sendmail(self.mail_user, self.mail_receivers, message.as_string())
            print('发送邮件成功!')
        except Exception as e:
            print('发邮件---->失败!原因:', e)

    def mail_close(self):
        """ 关闭邮箱资源 """
        self.smtp.close()

此模块使用python自带模块smtp实现发邮件的功能,比较简单,只需将相关配置文件读取进来即可!

程序使用方法

好了介绍完上面的三个主要模块,来说下如何使用:

|--config
    |--linux_config.ini     (linux服务器配置文件)
    |--mail_settings.ini    (邮箱设置配置文件)
    |--time_config.ini      (cron定时设置配置文件)

在这里,使用者可以配置自己所需要的相关信息

linux_config.ini:

# linux远程服务ip,多个服务器用,隔开,例如(10.10.111.1,10.10.111.2,....)
[server-ip]
ip = 10.10.111.1,10.10.111.2,....

#对应用户名,密码,多个服务器用;隔开,例如(user1,pwd1;user2,pwd2;....)
[server-login]
login_info = user1,pwd1;user2,pwd2;....

# 不同ip作为key值,不同命令作为value值
[cmd]
10.10.111.1 = cd $(locate taskmngdomain1/nohuplogs) ; tail -50 *log*`date +%F`*
10.10.111.2 = cd $(locate taskmngdomain2/nohuplogs) ; tail -50 *log*`date +%F`*

mail_settings.ini:

# 邮箱服务端、端口
[mail-server]
mail_host = smtp.xxxx.com
mail_port = 25

# 邮箱客户端(发邮箱的人),用户名、密码
[mail-client]
mail_user = xxxx@xxx.com
mail_pwd = xxxxx

# 收邮件的人邮箱,多个用逗号隔开
[mail-receivers]
mail_receivers = xxxx@qq.com,xxxx@163.com

time_config.ini:
此配置文件可以参考cron的写法!

;year (int|str) – 4-digit year
;month (int|str) – month (1-12)
;day (int|str) – day of the (1-31)
;week (int|str) – ISO week (1-53)
;day_of_week (int|str) – number or name of weekday (0-6 or mon,tue,wed,thu,fri,sat,sun)
;hour (int|str) – hour (0-23)
;minute (int|str) – minute (0-59)
;second (int|str) – second (0-59)
[cron]
year = *
month = *
day = *
week = *
day_of_week = *
hour = *
minute = 0/1
second = 0

结果展示

如图下:开启run后,程序会根据定时触发…随后收到邮件:

《python实现自动化之路(自动巡检服务器告警)》

总结

	emmmm.....		emmmm.....		emmmm.....      emmmm.....

《python实现自动化之路(自动巡检服务器告警)》

以上就是本次自动化实现的全过程~
开源社会共同成长!献上我的源代码:
https://github.com/unlimitbladeworks/monitor-linux
欢迎大家star ⭐️or fork 🍴 哦!

点赞