前情概要

  原syslog服务器只收集不推送日志,可以实时展示,服务器在海外内网,办公网做的有分流,到日志服务器的流量送到香港,其余流量国内,疫情期间在家办公,每次连接需要拨海外l2tp,挂着梯子访问国内时延较大影响办公,所以日志服务器基本一天登录一次,然后就错过了重要的error信息-_-!,所以在家的几天做了两个方案,1是上篇博客中的数通技术,2就是做一个功能邮箱推送error级别以上的日志

功能

  django前端用以日志的展示和搜索,后端用于日志采集与邮件推送

目录结构

-swlog

---swlog

------  setting.py

------  url.py

---log

------  models.py

------  views.py

------  limit.py

---sock

------  bin.py

------  formstr.py

------  sendmail.py

------  sql.py

---templates

------  log.html

------  login.html

urls

 1 from django.contrib import admin
2 from django.urls import path
3 from log import views
4 import threading
5 from log.sock.bin import logserver
6 urlpatterns = [
7 path('admin/', admin.site.urls),
8 path('login.html/', views.login),
9 path('log.html/', views.log),
10 ]
11 t1 = threading.Thread(target=logserver)
12 t1.start()

urls.py

后端分页

 1 class limit:
2 def limit(self,res,obj):
3 limit = int(res.GET.get('limit',1))
4 pagelimit = int(res.GET.get('pagelimit',50))
5 startlimit = (limit-1)*pagelimit
6 endlimit = limit*pagelimit
7 logdb = obj[startlimit:endlimit]
8 page_count,lastpage_count = divmod(obj.count(),pagelimit)
9 if lastpage_count:
10 page_count +=1
11 startpage = 1
12 endpage = page_count
13 hrefli=[]
14 hrefli.append('<form style="display: inline;" method="GET" action="%s">每页显示<select name="pagelimit"><option>30</option><option>50</option><option>100</option><option>300</option><option>500</option></select><input type="submit" value = "确定"></form>'%res.path)
15 if limit !=1:
16 hrefli.append('<a class="page" href="%s?limit=%s">%s</a>'%(res.path,limit-1,'上一页'))
17 for x in range(startpage,endpage+1):
18 if limit+3 < x or x <limit -3:
19 hrefli.append('<a class="page pitch hidden" href="%s?limit=%s">%s</a>'%(res.path,x,x))
20 elif x == limit:
21 hrefli.append('<a class="page pitch" href="%s?limit=%s">%s</a>'%(res.path,x,x))
22 else:
23 hrefli.append('<a class="page unpitch" href="%s?limit=%s">%s</a>'%(res.path,x,x))
24 if limit != endpage:
25 hrefli.append('<a class="page" href="%s?limit=%s">%s</a>'%(res.path,limit+1,'下一页'))
26 href=''.join(hrefli)
27 return href,logdb

limit.py

view后端进行登录验证,拉取日志

 1 from django.shortcuts import render,redirect,HttpResponse
2 from log import models
3 from log.limit import limit
4 from django.views.decorators.csrf import csrf_exempt
5 from functools import wraps
6 from django.utils.safestring import mark_safe
7 def auth(func):
8 @wraps(func)
9 def check_login(res,*args,**kwargs):
10 try:
11 res.session['name']
12 return func(res,*args,**kwargs)
13 except:
14 return render(res,'login.html')
15
16 return check_login
17
18
19 @csrf_exempt
20 def login(res):
21 if res.method == 'GET':
22 return render(res,'login.html')
23 elif res.method == 'POST':
24 username = res.POST.get('username')
25 passwd = res.POST.get('passwd')
26 if models.login.objects.filter(username=username,passwd=passwd):
27 res.session.set_expiry(3600)
28 res.session['name']=username
29
30 return redirect('/log.html')
31 else:
32 error = '用户名或密码错误'
33 return render(res,'login.html',{'error':error})
34
35 @auth
36 @csrf_exempt
37 def log(res):
38 obj = models.log.objects
39 if res.method =='GET':
40 pagelimit = limit()
41 html_lable,logdb = pagelimit.limit(res,obj.all())
42 return render(res,'log.html',{'logdb':logdb,'limit':mark_safe(html_lable)})
43 elif res.method == 'POST':
44 if res.POST.get('search'):
45 from django.db.models import Q
46 data = res.POST.get('search')
47 logdb = obj.filter(Q(time__contains=data)| Q(host__contains=data)| Q(level__contains=data)| Q(message__contains=data))[0:500]
48 return render(res,'log.html',{'logdb':logdb})
49 elif res.POST.get('day'):
50 import time
51 day = int(res.POST.get('day'))-1
52 h_time = time.strftime('%Y-%m-%d',time.localtime(time.time()-86400*day))
53 delete_count = obj.filter(time__lt=h_time).count()
54 obj.filter(time__lt=h_time).delete()
55 return redirect('/log.html')
56 return redirect('/log.html')
57
58

views.py

templates前端简单做两个页面,一个用于登录,另一个用于展示和搜索

 1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta http-equiv="X-UA-Compatible" content="IE=edge">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <title>登录</title>
8 <style>
9 .input{width: 300px; height: 20px;margin-top: 10px;}
10 </style>
11 </head>
12 <body style="background-color: royalblue;">
13
14 <div style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);">
15
16
17 <form action="/login.html/" method="POST">
18 <h1 style="text-align: center; color: seashell;">日志管理系统</h1>
19 <input class="input" name="username" type="text" placeholder=username>
20 <br>
21 <input class="input" name="passwd" type="password" placeholder=passwd>
22 <br>
23 <button style="width: 300px;height: 30px; margin-top: 10px;" >登录</button>
24 <span>{{error}}</span>
25 </form>
26 </div>
27 </body>
28
29 </html>

login.html

 1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta http-equiv="X-UA-Compatible" content="IE=edge">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <meta http-equiv="Refresh" content="60" >
8 <title>Document</title>
9 <style>
10 *{margin: 0;padding: 0;}
11 .top{position: fixed;top: 0px;height: 100px;width: 100%;z-index: 100;background-color: blanchedalmond;}
12 .search{float: right;margin-right: 50px;}
13 .error,.crit,.alert,.emerg{background-color: rgb(243, 67, 67);}
14 .debug,.notice,.info{background-color: cornflowerblue;}
15 .warning{background-color: yellow;}
16 td {white-space:nowrap;}
17 body{background-color:whitesmoke;}
18 .hidden{display:none ;}
19 .pitch{background-color:black;color: white;}
20 .unpitch{background-color: white;color: black;}
21 a{margin-left: 10px;}
22 a:hover{background-color: cornflowerblue;}
23 </style>
24
25 </head>
26 <body>
27 <div class="top" >
28 <h3 style="text-align: center;">日志管理系统</h3>
29 <form action="/log.html/" method="POST" class="search">
30 <input type="text" id="search" name="search">
31 <span>
32 <input type="submit" value="搜索">
33 </span>
34 </form>
35
36 {{limit}}
37 <form action="/log.html/" method="POST" style="margin-top:10px">
38 <span>清除</span>
39 <select name="day">
40 <option>3</option>
41 <option>7</option>
42 <option>15</option>
43 <option>30</option>
44 </select>
45 <span>天历史数据</span>
46 <input type="submit" value="确定">
47 </form>
48
49 </div>
50 <div class = 'message'>
51 <table border="1px" style="width: 100%;">
52 <tr>
53 <td>time</td>
54 <td>host</td>
55 <td>level</td>
56 <td>message</td>
57 </tr>
58
59 {%for mess in logdb%}
60 <tr class = {{mess.level}}>
61 <td>{{mess.time}}</td>
62 <td>{{mess.host}}</td>
63 <td>{{mess.level}}</td>
64 <td>{{mess.message}}</td>
65 </tr>
66 {%endfor%}
67
68 </table>
69
70 </div>
71 </body>
72 </html>

log.html

日志采集与邮件推送模块

 1 import pymysql,time
2 class db:
3 def __init__(self):
4 self.conn = pymysql.connect(host='127.0.0.1',port = 3306,user = 'root',passwd = 'd****', db='log')
5 self.coursor = self.conn.cursor()
6 def write(self,host,level,message):
7 ltime = time.strftime('%Y-%m-%d',time.localtime(time.time()))
8 sql = 'insert into swlog_log(host,level,message,time) values("%s","%s","%s","%s")'%(host,level,message,ltime)
9 self.coursor.execute(sql)
10 self.conn.commit()
11 self.conn.close()

sql.py

 1 import email
2 import smtplib
3 from email.header import Header
4 from email.utils import formataddr
5 from email.mime.text import MIMEText
6 class sendemail():
7 def __init__(self,email_list,content,subject):
8 self.email_list = email_list
9 self.content = content
10 self.subject = subject
11 def sendemail(self):
12 msg = MIMEText(self.content,'plain','utf-8')
13 msg['from'] = formataddr(['dark','97****@qq.com'])
14 msg['subject'] = self.subject
15 service = smtplib.SMTP('smtp.qq.com')
16 service.login('97****@qq.com','ilz****')
17 service.sendmail('97****@qq.com',self.email_list,msg.as_string())
18 service.quit()

sendmail.py

 1 import re
2 def syslog(date):
3 date = date.replace('\"','\'')
4 pri = re.findall('\d+',date)[0]
5 pri = int(pri)
6 level = re.findall('<\d+>',date)[0]
7 date = date.replace(level,'').strip()
8 if pri%8 == 0:
9 div_class = 'emerg'
10 elif pri%8 == 1:
11 div_class = 'alert'
12 elif pri%8 == 2:
13 div_class = 'crit'
14 elif pri%8 == 3:
15 div_class = 'error'
16 elif pri%8 == 4:
17 div_class = 'warning'
18 elif pri%8 == 5:
19 div_class = 'notice'
20 elif pri%8 == 6:
21 div_class = 'info'
22 elif pri%8 == 7:
23 div_class ='debug '
24 return date,div_class

formstr.py

 1 import socket,re,os,subprocess
2 from log.sock import formstr,sql
3 from log.sock.sendmail import sendemail
4 import time
5
6 def logserver():
7 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
8 address = ('10.0.64.61',514)
9 s.bind(address)
10 mail_level = ['error','crit','alert','emerg']
11 while True:
12 data,address = s.recvfrom(10240)
13 data = data.decode(encoding='utf8')
14 data,div_class = formstr.syslog(data)
15 write_db = sql.db()
16 write_db.write(address[0],div_class,data)
17 if div_class in mail_level:
18 title = '主机%s,严重等级%s'%(address[0],div_class)
19 mail = sendemail(['cs11241991@163.com','dark@lonlife-inc.com'],data,title)
20 mail.sendemail()

bin.py

功能测试

python模块,邮件推送交换机error级别以上log,django前端展示的更多相关文章

  1. python模块安装报错 :error: command 'gcc' failed with exit status 1

    参考:http://blog.csdn.net/fenglifeng1987/article/details/38057193 解决方法 yum install gcc libffi-devel py ...

  2. Python模块探秘 Smtplib发送带有各种附件的邮件

    这两天对Python的邮件模块比较感兴趣,于是就查了查资料.同时在实际的编码过程中也遇到了各种各样的问题.下面我就来分享一下我与smtplib的故事. 前提条件 我的上一篇博文里面讲解了,发送邮件必须 ...

  3. python实现邮件接口——smtplib模块

    1. 思路 使用脚本发送邮件的思路其实和客户端发送邮件一样,过程都是: 登录 —> 写邮件 —> 发送 只不过通过脚本发送时我们需要考虑到整个过程的方方面面.以下为思路导图: 2. Pyt ...

  4. Python模块 --- 最高级别程序组织单元

    模块 --- 最高级别程序组织单元 <Python学习手册>笔记 import 导入1个模块 from 获取模块指定变量名 imp.reload 重新载入模块文件代码的方法 模块作用 代码 ...

  5. Python 操作Zabbix API 获取ERROR级别告警信息并打印

    1.需求:有一个语音合成播报项目,要实时获取zabbix的ERROR级别以上告警信息,将该信息合成语音播报出去.(合成语音及播报已经完成) 2.现实:整理zabbix告警级别,将不太重要的告警放到ER ...

  6. 编译boost python模块遇到的错误:../../libraries/boost_1_44_0/boost/python/detail/wrap_python.hpp:75:24: fatal error: patchlevel.h: No such file or directory

    就是遇到类似标题上面的错误. 原因是没有安装对应python的python-dev依赖,不然编译到boost python模块的时候就会出错. 所以解决方案是sudo apt-get install ...

  7. 【转】python模块分析之logging日志(四)

    [转]python模块分析之logging日志(四) python的logging模块是用来写日志的,是python的标准模块. 系列文章 python模块分析之random(一) python模块分 ...

  8. python模块分析之logging日志(四)

    前言 python的logging模块是用来设置日志的,是python的标准模块. 系列文章 python模块分析之random(一) python模块分析之hashlib加密(二) python模块 ...

  9. python模块大全

    python模块大全2018年01月25日 13:38:55 mcj1314bb 阅读数:3049 pymatgen multidict yarl regex gvar tifffile jupyte ...

随机推荐

  1. ElasticSearch-学习笔记04-复杂查询

    service package com.huarui.service; import com.huarui.entity.SearchEntity; import com.huarui.exectio ...

  2. Pandas基础笔记

    Basic knowledge of Pandas pandas库是以numpy库为基础建成的,是python数据分析的核心库.也正因如此,pandas内的数据结构与numpy的数组有许多相似的地方. ...

  3. Cookie与HttpSession对象

    Cookie与HttpSession对象的作用 维护客户端浏览器与服务端会话状态的两个对象. 由于HTTP协议是一个无状态的协议,因此服务端不会记录当前客户端浏览器的访问状态 有些时候需要服务端能够记 ...

  4. Linux 0.11源码阅读笔记-文件管理

    Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...

  5. 微信小程序animation动画2种方法

    这里介绍 2 种方法一种是常规的小程序方法操作,另一种是引入动画库 1. 常规动画操作设置 wxml: <view> <view bindtap="clickMe" ...

  6. OllyDbg---call和ret指令

    call和ret call指令 cal指令是转移到指定的子程序处,后面紧跟的操作数就是给定的地址. 例如,call 401362表示转移到地址401362处,调用401362处的子程序,当子程序调用完 ...

  7. Kubernetes 解决方案-图解

  8. Java-GUI编程之菜单组件

    前面讲解了如果构建GUI界面,其实就是把一些GUI的组件,按照一定的布局放入到容器中展示就可以了.在实际开发中,除了主界面,还有一类比较重要的内容就是菜单相关组件,可以通过菜单相关组件很方便的使用特定 ...

  9. 正则表达式小技巧,sql中in的字符串处理

    工作中我经常写sql,当写带in的语句时,需要敲好多单引号,逗号,敲写起来容易易出错.因此,我写了一个小工具,处理这种繁琐工作.原理简单,利用正则表达式匹配.替换. 先看界面,一个html页面,包含三 ...

  10. switch 用法

    1.语法格式和规则 switch case 语句语法格式如下: switch(expression){ case value : //语句 break; //可选 case value : //语句 ...