服务器巡检并汇总Excel发送邮件通知

post thumb
Python
作者 Louis 发表于 2020年1月10日

背景

接到一个需求, 要求每天都要服务器巡检, 并统计巡检信息, 归档备查. 公司服务器有13台, 一台台巡查, 手动操作又很繁琐, 身为运维, 决不能让重复性劳动占据太多时间.

解决思路

  • 写一个监控脚本, 监控服务器的所有的状态, 如服务器磁盘, CPU, 内存, IP, 主机名, load等.
  • 将监控的服务器状态转为文本.
  • 将文本内容转化为Excel.
  • 将Excel发送相关人员邮箱.

想到就要干, 开始写脚本

项目结构

.
├── a.sh            #服务器巡检脚本
├── manage.log      #服务器执行脚本日志
├── manage.sh	    #总执行脚本
├── py3			    #python3 虚拟环境
├── __pycache__	    #python3编译生成的cache文件夹
├── server-monitor  #xls文件归档目录
└── transformation.py #python脚本

shell巡检脚本

$ cat > a.sh <<-eof
#!/usr/bin/env bash
#获取主机名
system_hostname=$(hostname | awk '{print $1}')

#获取服务器IP
system_ip=$(curl http://100.100.100.200/latest/meta-data/private-ipv4)

#获取总内存
mem_total=$(free -m | grep Mem| awk -F " " '{print $2}')

#获取剩余内存
mem_free=$(free -m | grep "Mem" | awk '{print $4+$6}')

#获取已用内存
mem_use=$(free -m | grep Mem| awk -F " " '{print $3}')

#获取当前平均一分钟负载
load_1=`top -n 1 -b | grep average | awk -F ':' '{print $5}' | sed -e 's/\,//g' | awk -F " " '{print $1}'`

#获取当前平均五分钟负载
load_5=`top -n 1 -b | grep average | awk -F ':' '{print $5}' | sed -e 's/\,//g' | awk -F " " '{print $2}'`

#获取当前平均十五分钟负载
load_15=`top -n 1 -b | grep average | awk -F ':' '{print $5}' | sed -e 's/\,//g' | awk -F " " '{print $3}'`

#取磁盘信息,并加入描述
disk_1=$(df -Ph |grep -v overlay|grep -v grep| awk '{if(+$5>2) print "分区:"$1,"总空间:"$2,"使用空间:"$3,"剩余空间:"$4,"磁盘使用率:"$5}')

#拆分
disk_fq=$(df -Ph|grep -v overlay|grep -v grep  | awk '{if(+$5>2) print "分区:"$1}')
disk_to=$(df -Ph|grep -v overlay|grep -v grep  | awk '{if(+$5>2) print "总空间:"$2}')
disk_us=$(df -Ph|grep -v overlay|grep -v grep  | awk '{if(+$5>2) print "使用空间:"$3}')
disk_fe=$(df -Ph|grep -v overlay|grep -v grep  | awk '{if(+$5>2) print "剩余空间:"$4}')
disk_ul=$(df -Ph|grep -v overlay|grep -v grep  | awk '{if(+$5>2) print "磁盘使用率:"$5}')
disk_ux=$(df -Ph|grep -v overlay|grep -v grep  | awk '{if(+$5>2) print $5}')

#信息存放的文件路径
[ -d "/tmp/sftp/log" ] || mkdir /tmp/sftp/log -p
path=/tmp/sftp/log/monitor_"$system_ip".txt

#内存阈值
mem_mo='60'

echo -e " " > $path
echo -e "主机名:"$system_hostname >> $path
echo -e "服务器IP:"$system_ip >> $path
if [[ $(echo $disk_ux | sed s/%//g) -gt 50 ]]
   then
    echo $disk_fq >>$path
    echo $disk_to >>$path
    echo $disk_us >>$path
    echo $disk_fe >>$path
    echo $disk_ul >>$path
    echo 磁盘巡检状态:不正常 >>$path
   else
    echo $disk_fq >>$path
    echo $disk_to >>$path
    echo $disk_us >>$path
    echo $disk_fe >>$path
    echo $disk_ul >>$path
    echo 磁盘巡检状态:正常 >>$path
 fi
PERCENT=$(printf "%d%%" $(($mem_use*100/$mem_total)))
PERCENT_1=$(echo $PERCENT|sed 's/%//g')
if [[ $PERCENT_1 -gt $mem_mo ]]
    then
     echo -e 总内存大小:$mem_total MB>> $path
     echo -e 已用内存:$mem_use MB >> $path
     echo -e 内存剩余大小:$mem_free MB >> $path
     echo -e 内存使用率:$PERCENT >> $path
     echo -e 内存巡检结果:不正常 >> $path
    else
     echo -e 总内存大小:$mem_total MB>> $path
     echo -e 已用内存:$mem_use MB >> $path
     echo -e 内存剩余大小:$mem_free MB >> $path
     echo -e 内存使用率:$PERCENT >> $path
     echo 内存巡检结果:正常 >> $path
fi
    echo -e 平均1分钟负载:$load_1"\n"平均5分钟负载:$load_5"\n"平均15分钟:$load_15 >> $path

执行脚本

$ sh a.sh
$ cat /tmp/sftp/log/monitor_172.16.111.118.txt

主机名:iZbp167av7wvow0nqs68rlZ
服务器IP:172.16.111.118
分区:/dev/vda1
总空间:296G
使用空间:78G
剩余空间:204G
磁盘使用率:28%
磁盘巡检状态:正常
总内存大小:16081 MB
已用内存:15806 MB
内存剩余大小:882 MB
内存使用率:98%
内存巡检结果:不正常
平均1分钟负载:1.08
平均5分钟负载:1.08
平均15分钟:1.01

python将文本txt转为Excel

$ cat transformation.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import xlwt
import datetime
#import sendmail
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
#每天的几点发送邮件及附件加时间戳
now = datetime.datetime.now().strftime('%Y-%m-%d-%H') 
mail_host="smtp.mxhichina.com"  #设置服务器
mail_user="louis@wangke.co"    #用户名
mail_pass="123456"   #口令
style = "font:colour_index red; align: wrap on, vert centre, horiz center;"
styleb = xlwt.XFStyle()  # 创建一个样式对象,初始化样式
al = xlwt.Alignment()
al.horz = 0x02      # 设置水平居中
al.vert = 0x01      # 设置垂直居中
styleb.alignment = al
red_style = xlwt.easyxf(style)
title_style = xlwt.easyxf('font: height 200, name Arial Black, colour_index blue, bold on; align: wrap on, vert centre, horiz center;' )
def getlist():  # 读取txt
    with open('hebing.txt', 'r+',encoding='utf-8') as f:
        s1 = f.readlines()
    f.close()
    s2 = []
    for i in s1:
            if '\n' in i:
                    s2.append(i[:-1])
            else:
                    s2.append(i)
    return s2
def fenge():  # 分割
    list0 = []  # 存贮空格行
    for num, val0 in enumerate(getlist()):
        if val0.split(':')[0] == '主机名':
            list0.append(num)
    list0.append(len(getlist()))
    list1 = []   # 存贮内容
    for num1,val1 in enumerate(list0[1:]):
        temp = getlist()[list0[num1]:list0[num1+1]]
        list1.append(temp)
    return list1
def wxls():   # 写入表格
    title = ['主机名','服务器IP','分区','总空间','使用空间','剩余空间','磁盘使用率','磁盘巡检状态','总内存大小',
    '已用内存','内存剩余大小','内存使用率','内存巡检结果','平均1分钟负载','平均5分钟负载','平均15分钟', 'ceshi']
    workbook = xlwt.Workbook(encoding='utf-8')
    worksheet = workbook.add_sheet('sheet1')
    for i1, val in enumerate(title):
        worksheet.write(0, i1, label=val,style = title_style)
        first_col = worksheet.col(i1)
        first_col.width = 180 * 20
    for i2, val2 in enumerate(title):
        for i3, val3 in enumerate(fenge()):
            for j in val3:
                if j.split(':')[0] == val2:
                    #print i2,i3,j.split(':')[1].decode('utf8')
                    if j.split(':')[1] == '不正常':
                        worksheet.write(i3 + 1, i2, label=j.split(':')[1],style=red_style)
                    else:
                        worksheet.write(i3+1, i2, label=j.split(':')[1] ,style = styleb)
    name = now + 'miontior.xls'
    workbook.save(name)


def send_mail(): 
    sender = 'louis@wangke.co'
    receivers = ['louis@wangke.co']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
     
    #创建一个带附件的实例
    message = MIMEMultipart()
    message['From'] = Header("louis@wangke.co", 'utf-8')
    message['To'] =  Header("louis@wangke.co", 'utf-8')
    subject = now+'服务器巡检表格'
    message['Subject'] = Header(subject, 'utf-8')
     
    #邮件正文内容
    message.attach(MIMEText('各位好: \n' + now + ': 生产环境各服务器状态见附件.', 'plain', 'utf-8'))
     
    # 构造附件1,传送当前目录下的 test.txt 文件
    att1 = MIMEText(open(now + 'miontior.xls', 'rb').read(), 'base64', 'utf-8')
    att1["Content-Type"] = 'application/octet-stream'
    # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
    att1["Content-Disposition"] = 'attachment; filename="{}moniter.xls"'.format(now+'-')
    message.attach(att1)
     
    try:
        smtpObj = smtplib.SMTP_SSL(mail_host, 465)
        smtpObj.login(mail_user,mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print ("邮件发送成功")
    except smtplib.SMTPException:
        print ("Error: 无法发送邮件")

wxls()
send_mail()

批量操作

上面的都是单机操作, 单机操作其实没必要写脚本了, 手动也花不了多少时间. 万一服务器有100台呢? 每台执行相同的命令, 依旧没有解决问题. 这里, 可以将监控的文本txt全部fecth到某台服务器进行集中管理, 即可解决痛点. 使用的是anisible进行管理的主机

$ cat manage.sh
#!/bin/bash
DATE=$(date +%F-%H:%M:%S)
source py3/bin/activate
echo "$DATE exec $0" >> manage.log 

## 所有主机执行a.sh, 即完成服务器巡检操作
ansible all -m script -a "/data/louis/a.sh"  >> manage.log

## 将所有主机的生成的txt文件同步到ansible管理的主机上
ansible all -m synchronize -a "src=/tmp/sftp/log/ dest=/data/louis mode=pull"  >> manage.log

## 生成主机合并的信息文件
> hebing.txt
## 遍历同步过来的主机巡检信息文件, 追加至文件
for file in `ls ./mo*.txt` ; do
	cat $file >> hebing.txt
done

## 将合并的信息转为xls文件

python3.4 transformation.py >> manage.log

## 将不需要的文件删掉并归档.
rm -f *.txt
mv *.xls server-monitor

关于ansible的细节操作就不在重复了, 具体细节点击标签, 查看ansible相关文档.

over~

上一篇
记一次linux的bios引导失败