目錄
- 項目介紹和源碼;
- 拿來即用的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); } } });
結語
這裏說了下怎麼實現查看服務器已經存在的日誌,可是這個方法自己是存在缺陷的,它只適用於比較小的日誌文件的顯示,大文件須要很長一段時間。數據庫