目录
- 项目介绍和源码;
- 拿来即用的bootstrap模板;
- 服务器SSH服务配置与python中paramiko的使用;
- 用户登录与session;
- 最简单的实践之修改服务器时间;
- 查看和修改服务器配置与数据库的路由;
- 基于websocket的实时日志实现;
- 查看服务器中的日志与前端的datatable的利用;
- 重启服务器进程。
前言
除了可以支持实时的日志以外,小项目还须要增长一个回看日志的页面,页面的效果如图1所示。这个页面的做用是按用户的需求(日志的日期、日志内容的时间、日志的内容)筛选出须要的日志而且展现到这个datatable的动态表格中,它的实现原理很简单,可是具备必定的局限性。可是能够知足一些自己很少的日志的查看,如错误日志、测试日志、服务器日志这些。javascript
功能内容
显示页面
页面由一个Datatable和本身写的一些input组件组成,其html脚本以下。css
{% extends "./base.html" %} {% block othercss %} <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" /> {% endblock %} {% block title %}{{ title }}{% endblock %} {% block log %}{{ title }}{% endblock %} {% block username %}{{ username }}{% endblock %} {% block mainbody %} <section class="wrapper site-min-height"> <h3><i class="fa fa-angle-right"></i> 查找日志 <i class="fa fa-desktop"></i></h3> <div class="row mt"> <div class="form-panel"> <div class="col-lg-12 row mt"> <div class="col-sm-6"> <h4 class="mb" style="float:left;dispaly:block;">查找日志</h4> </div> <div class="col-sm-5 search"> <input type="text" class="form-control" id='contentkey' placeholder='关键内容或日志名(可填)'> <input type="text" class="form-control" id="date"> <div class="row"> <div class="col-sm-8"> <input type="text" class="form-control" id="time" placeholder='选择时间段(必填)'> </div> <div class="col-sm-4"> <button type="button" class="btn btn-theme02" id='searchlog' style="float:right;">查找日志</button> </div> </div> </div> </div> <div> <div class="progress progress-striped active" style="display:none" id="loading"> <div class="progress-bar" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div> </div> <table id="logtable" class="table-striped dataTable table-advance table-hover" style="word-break:break-all;"> <thead> <tr> <th style="width:25%;">日志时间</th> <th style="width:15%;">名字</th> <th>日志内容</th> </tr> </thead> <tbody id="log"> </tbody> </table> </div> </div> </div> </section> {% endblock %}
控制这个html界面的javascript代码以下,代码中laydate
组件的做用是针对图2中的蓝框中的时间选择器,它的引用在文章最简单的实践之修改服务器时间中提到过,具体的使用方法能够移步文章layDate 日期与时间组件, $('#logtable').DataTable({...})
用来初始化一个定制的动态响应表格,后文中会具体说说它的使用。当用户填好内容以后点击查找日志按钮,会执行$("#searchlog").click(function(){...})
函数,它会依次判断日期、时间段是否已经填写,因为筛选日志时候用的是时间段,因此还会判断一下首尾时间是否相等。html
{% block scripts %} <script> // 获取当前的日期,在用户选择日期的时候input栏默认显示为当前日期 var formatDate = function (date) { var y = date.getFullYear(); var m = date.getMonth() + 1; m = m < 10 ? '0' + m : m; var d = date.getDate(); d = d < 10 ? ('0' + d) : d; return y + '-' + m + '-' + d; }; $(document).ready(function (){ $('#logtable').DataTable({ "scrollCollapse": true, 'columnDefs':[{ 'targets' : [0,1,2], //除时间列之外都不排序 'orderable' : false }], "order": [[0 , "asc" ]], "oLanguage": { "sZeroRecords": "无结果!", "sSearch": "日志过滤:", }, }); laydate.render({ theme: 'molv', elem: '#date', // input栏默认当前日期 value: formatDate(new Date()) }); // 时间范围 laydate.render({ theme: 'molv', elem: '#time', type: 'time', format: 'H点', range: true }); }); $("#searchlog").click(function(){ keycontent = $("#contentkey").val(); date = $("#date").val(); if(date == ''){ swal('', '请选择日期!', 'error') return ; } time = $("#time").val(); if(time == ''){ swal('', '请填写时间段!', 'error') return ; } // 断定首尾时间是否相等,因为是取时间段,首尾时间相等时是不容许的 _time = time.split("-"); begin_time = _time[0].replace(/\s/ig,''); end_time = _time[1].replace(/\s/ig,''); if(begin_time == end_time){ swal('', '首位时间相等,请从新输入!', 'error') return ; } var table = $('#logtable').DataTable().clear().draw(); table.clear().draw(); $.ajax({ url:"searchlog", type:'POST', data:{'keycontent':keycontent, 'date':date, 'time':time}, success: function(arg){ ret = eval(arg); logs = ret.logs; for(j = 0,len = logs.length; j < len; j++) { logtime = logs[j][0]; logname = logs[j][1]; logcontent = logs[j][2]; table.row.add([logtime,logname,logcontent]).draw(true); } } }); }); </script> <script src="/templates/servermaterial/assets/laydate/laydate.js"></script> <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script> {% endblock %}
添加server/urls.py中的url函数url(r'^searchlog', views.searchlog)
。
在server/views.py中添加页面渲染函数log和由url请求过来的searchlog功能函数:前端
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib.auth import logout from django.shortcuts import render_to_response from django.http import JsonResponse from django.contrib.auth.decorators import login_required import json import time '''如下这些函数是渲染前端模板的函数''' # 服务器的名字 htmltitle = '服务器工具' # 页面渲染函数 @login_required(login_url='/loginpage') def log(request): username = request.session.get('username') pagedict = {'title': htmltitle, 'username': username} return render_to_response("servermaterial/log.html", pagedict) # 查找日志 def searchlog(request): ret = {'status': False, 'logs': ''} if request.method == 'POST': from WebTool.functions import get_filter_log # 关键内容 keycontent = request.POST.get('keycontent') # 日志日期 logdate = request.POST.get('date') # 日志筛选的时间段 logtime = request.POST.get('time') filter_list = [keycontent, logdate, logtime] logs = get_filter_log(filter_list) ret['status'] = True ret['logs'] = logs return JsonResponse(ret)
searchlog
中的get_filter_log
函数是根据服务器中日志的形式单独定制的,因此在前面的文章中没有写过它的实现,下面的服务器中的日志内容中会实现一个get_filter_log
函数。java
服务器中的日志内容
- 服务器中日志格式
如图3,服务器中的日志名字规律用log-(日期)的格式存放着,每一个txt日志的文档内容都形如图4所示,日志中会记录条目生成的时间,名字和内容。python
- paramiko实现get_filter_log函数
根据日志的名字规律和格式能够单独写一个paramiko函数以下,写好的函数放在Webtool/Webtool中的functions文件中。用到了一些简单的Linux命令行。
'find /home/logs -name *' + filter_date + '*.txt'
用来在日志文件夹下查找给定日期的日志文件。
| xargs cat
将查找到的结果执行cat。
grep -E \'' + filter_time + '\' | grep -i ' + filter_content
用来在cat的结果中查找符合时间段和内容的结果。
能够看出这里,查找日志的方式是使用cat
一步到位的,因此对于日志内容很大的状况,须要很长一段时间,特别是还要传递到前端的datatable中显示。jquery
# 得到服务器的日志 def get_filter_log(filter_list): ssh = login_server_by_pwd() # 筛选日志的时期 filter_date = filter_list[1].replace('-', '') _filter_date = filter_list[1] # 筛选日志的时间 filter_content = filter_list[0] # 筛选日志的时间范围 time_range = filter_list[2] beg_time, end_time = re.findall("\d+", time_range) beg_time = int(beg_time) end_time = int(end_time) if beg_time > end_time: beg_time, end_time = end_time, beg_time # 根据首尾时间生成每一个单独时间用于日志帅选 time_list = ["%02d" % num for num in range(beg_time, end_time)] filter_time = '' # 可被Linux执行的命令行 for _time in time_list: filter_time += (_filter_date + ' ' + _time + ':|') filter_time = filter_time[:-1] # 检查是否存在该天的日志 stdin, stdout, stderr = ssh.exec_command('find /home/logs -name *' + filter_date + '*.txt') istxt = bool(len(stdout.read())) # 若是存在改天的日志 if istxt: # 若是有须要进一步筛选内容 if filter_content: filter_command = 'find /home/logs -name "*' \ + filter_date + '*.txt" | xargs cat | grep -E \'' \ + filter_time + '\' | grep -i ' + filter_content else: filter_command = 'find /home/logs -name "*' \ + filter_date + '*.txt" | xargs cat | grep -E \'' + filter_time + '\'' print filter_command stdin, stdout, stderr = ssh.exec_command(filter_command) raw_log = stdout.read() log = re.findall("\[(.*?)\]\[(.*?)\],({.*})", raw_log) return log
Datatable的使用
关于Datatable的使用能够参考的文章不少,这里只是说下这个页面中dataatable的使用。它的javascript函数很简单,以下:web
$('#logtable').DataTable({ "scrollCollapse": true, 'columnDefs':[{ 'targets' : [1,2], // 除时间列之外都不排序,0列为时间,1列为名字,2列为内容 'orderable' : false }], "order": [[0 , "asc" ]], // 时间列默认按升序排列 "oLanguage": { "sZeroRecords": "无结果!", // 表格没有内容的时候显示无结果!,如图5红色框 "sSearch": "日志过滤:", // 搜索栏的提示,如图5蓝色框 }, });
下面的javascript代码经过ajax请求到后台以后,将后台传递上来的日志结果一个个增长到表格中,table.row.add([logtime,logname,logcontent]).draw(true)
这个函数用来向datatable中增长数据。ajax
$.ajax({ url:"searchlog", type:'POST', data:{'keycontent':keycontent, 'date':date, 'time':time}, success: function(arg){ ret = eval(arg); logs = ret.logs; for(j = 0,len = logs.length; j < len; j++) { logtime = logs[j][0]; logname = logs[j][1]; logcontent = logs[j][2]; table.row.add([logtime,logname,logcontent]).draw(true); } } });
结语
这里说了下怎么实现查看服务器已经存在的日志,可是这个方法自己是存在缺陷的,它只适用于比较小的日志文件的显示,大文件须要很长一段时间。数据库