目录
- 项目介绍和源码;
- 拿来即用的bootstrap模板;
- 服务器SSH服务配置与python中paramiko的使用;
- 用户登陆与session;
- 最简单的实践之修改服务器时间;
- 查看和修改服务器配置与数据库的路由;
- 基于websocket的实时日志实现;
- 查看服务器中的日志与前端的datatable的利用;
- 重启服务器进程。
前言
除了能够支持实时的日志之外,小项目还需要增加一个回看日志的页面,页面的效果如图1所示。这个页面的作用是按用户的需求(日志的日期、日志内容的时间、日志的内容)筛选出需要的日志并且展示到这个datatable的动态表格中,它的实现原理很简单,但是具有一定的局限性。但是可以满足一些本身不多的日志的查看,如错误日志、测试日志、服务器日志这些。
功能内容
显示页面
页面由一个Datatable和自己写的一些input组件组成,其html脚本如下。
{% 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(){...})
函数,它会依次判断日期、时间段是否已经填写,由于筛选日志时候用的是时间段,所以还会判断一下首尾时间是否相等。
{% 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_literalsfrom 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'] = Trueret['logs'] = logsreturn JsonResponse(ret)
searchlog
中的get_filter_log
函数是根据服务器中日志的形式单独定制的,所以在前面的文章中没有写过它的实现,下面的服务器中的日志内容中会实现一个get_filter_log
函数。
服务器中的日志内容
- 服务器中日志格式
如图3,服务器中的日志名字规律用log-(日期)的格式存放着,每个txt日志的文档内容都形如图4所示,日志中会记录条目生成的时间,名字和内容。
- 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中显示。
# 获得服务器的日志
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_contentelse:filter_command = 'find /home/logs -name "*' \+ filter_date + '*.txt" | xargs cat | grep -E \'' + filter_time + '\''print filter_commandstdin, stdout, stderr = ssh.exec_command(filter_command)raw_log = stdout.read()log = re.findall("\[(.*?)\]\[(.*?)\],({.*})", raw_log)return log
Datatable的使用
关于Datatable的使用可以参考的文章很多,这里只是说下这个页面中dataatable的使用。它的javascript函数很简单,如下:
$('#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({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);}}});
结语
这里说了下怎么实现查看服务器已经存在的日志,但是这个方法本身是存在缺陷的,它只适用于比较小的日志文件的显示,大文件需要很长一段时间。