django搭建一個小型的服務器運維網站-查看服務器中的日誌與前端的datatable的利用

目錄

  1. 項目介紹和源碼
  2. 拿來即用的bootstrap模板
  3. 服務器SSH服務配置與python中paramiko的使用
  4. 用戶登錄與session;
  5. 最簡單的實踐之修改服務器時間
  6. 查看和修改服務器配置與數據庫的路由
  7. 基於websocket的實時日誌實現
  8. 查看服務器中的日誌與前端的datatable的利用;
  9. 重啓服務器進程

前言

  除了可以支持實時的日誌以外,小項目還須要增長一個回看日誌的頁面,頁面的效果如圖1所示。這個頁面的做用是按用戶的需求(日誌的日期、日誌內容的時間、日誌的內容)篩選出須要的日誌而且展現到這個datatable的動態表格中,它的實現原理很簡單,可是具備必定的侷限性。可是能夠知足一些自己很少的日誌的查看,如錯誤日誌、測試日誌、服務器日誌這些。javascript

圖1 頁面效果

功能內容

顯示頁面

  頁面由一個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

圖2 時間選擇界面

{% 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

圖3 日誌的格式

圖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中顯示。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藍色框
    },
});

圖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);
            }
        }
    });

結語

  這裏說了下怎麼實現查看服務器已經存在的日誌,可是這個方法自己是存在缺陷的,它只適用於比較小的日誌文件的顯示,大文件須要很長一段時間。數據庫

相關文章
相關標籤/搜索