django+nginx+xshell简易日志查询,接上<关于《rsyslog+mysql+loganalyzer搭建日志服务器<个人笔记>》的反思>
纠正一下之前在<关于《rsyslog+mysql+loganalyzer搭建日志服务器<个人笔记>》的反思>中说到的PHP+MySQL太慢,这里只是说我技术不好,没有技术可以修改这个开源的php日志程序罢了,当然,在做这个的时候,也是菜鸟一个,只是想自己尝试一下。高手可以直接跳过.....
首先,写在前面,因为上班空闲时间不多,只有忙里偷闲或自己回家的时间弄下,所以这个前后的时间就比较久了。
之前在上篇写到,是准备使用apache+django来搭建的,但是真的,我折腾了几次apache+wsgi的,我始终没有成功,无耐,我就没有再使用这个了。最终改为使用nginx+django来进行环境的搭建,这个搭建的相关的教程,如有意向的同学可以看这个.<nginx+uwsgi<django web环境的搭建>,个人感觉使用nginx+uwsgi,搭建的速度更快,而且几乎不用考虑什么版本的问题。真心为自己之前准备使用apache+wsgi而心痛自己。但是不得不说,有之前的经历所以看到这个nginx+uwsgi的思路,也一下子就清楚需要怎么操作了。
然后其它的就是一些代码相关的了,这里也当是记录下自己的搭建的步骤吧!大晚上的写得详细些吧!
首先是settings.py的文件:<导入log,还有最底下面的静态路径的设置,这里稍微注意一下>
1 """ 2 Django settings for searchlog project. 3 4 Generated by \'django-admin startproject\' using Django 1.8.7. 5 6 For more information on this file, see 7 https://docs.djangoproject.com/en/1.8/topics/settings/ 8 9 For the full list of settings and their values, see 10 https://docs.djangoproject.com/en/1.8/ref/settings/ 11 """ 12 13 # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 14 import os 15 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 18 19 # Quick-start development settings - unsuitable for production 20 # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ 21 22 # SECURITY WARNING: keep the secret key used in production secret! 23 SECRET_KEY = \'-qsjwm5iy%(yu+rq*u$3t4o+q(-sxn#o=0qt=mpb)8efto%lxd\' 24 25 # SECURITY WARNING: don\'t run with debug turned on in production! 26 import socket 27 if socket.gethostname() == \'samcao-Lenovo-IdeaPad-Y470\': 28 DEBUG = TEMPLATE_DEBUG = True 29 else: 30 DEBUG = TEMPLATE_DEBUG = False 31 32 #DEBUG = TEMPLATE_DEBUG = False 33 ALLOWED_HOSTS = [\'*\'] 34 35 # Application definition 36 37 INSTALLED_APPS = ( 38 \'django.contrib.admin\', 39 \'django.contrib.auth\', 40 \'django.contrib.contenttypes\', 41 \'django.contrib.sessions\', 42 \'django.contrib.messages\', 43 \'django.contrib.staticfiles\', 44 \'log\', 45 ) 46 47 MIDDLEWARE_CLASSES = ( 48 \'django.contrib.sessions.middleware.SessionMiddleware\', 49 \'django.middleware.locale.LocaleMiddleware\', 50 \'django.middleware.common.CommonMiddleware\', 51 #\'django.middleware.csrf.CsrfViewMiddleware\', 52 \'django.contrib.auth.middleware.AuthenticationMiddleware\', 53 \'django.contrib.auth.middleware.SessionAuthenticationMiddleware\', 54 \'django.contrib.messages.middleware.MessageMiddleware\', 55 \'django.middleware.clickjacking.XFrameOptionsMiddleware\', 56 \'django.middleware.security.SecurityMiddleware\', 57 ) 58 59 ROOT_URLCONF = \'searchlog.urls\' 60 61 TEMPLATES = [ 62 { 63 \'BACKEND\': \'django.template.backends.django.DjangoTemplates\', 64 \'DIRS\': [os.path.join(os.path.dirname(__file__),\'templates\').replace(\'\\\',\'/\'),], 65 \'APP_DIRS\': True, 66 \'OPTIONS\': { 67 \'context_processors\': [ 68 \'django.template.context_processors.debug\', 69 \'django.template.context_processors.request\', 70 \'django.contrib.auth.context_processors.auth\', 71 \'django.contrib.messages.context_processors.messages\', 72 ], 73 }, 74 }, 75 ] 76 77 WSGI_APPLICATION = \'searchlog.wsgi.application\' 78 79 80 # Database 81 # https://docs.djangoproject.com/en/1.8/ref/settings/#databases 82 83 DATABASES = { 84 \'default\': { 85 \'ENGINE\': \'django.db.backends.sqlite3\', 86 \'NAME\': os.path.join(BASE_DIR, \'db.sqlite3\'), 87 88 } 89 } 90 91 92 # Internationalization 93 # https://docs.djangoproject.com/en/1.8/topics/i18n/ 94 95 LANGUAGE_CODE = \'en-us\' 96 97 TIME_ZONE = \'UTC\' 98 99 USE_I18N = True 100 101 USE_L10N = True 102 103 USE_TZ = True 104 105 106 # Static files (CSS, JavaScript, Images) 107 # https://docs.djangoproject.com/en/1.8/howto/static-files/ 108 HERE = os.path.abspath(os.path.dirname(__file__)) 109 STATIC_URL = \'/static/\' 110 MEDIA_ROOT = os.path.join(HERE,\'static\') 111 MEDIA_URL = \'\' 112 ADMIN_MEDIA_PREFIX = \'/static/admin/\' 113 #STATIC_ROOT = \'/home/samcao/caodjango/searchlog/searchlog/static/\' 114 STATICFILES_DIRS = ( 115 os.path.join(BASE_DIR,\'static\'), 116 )
urls.py<就几个url,没有什么特殊的>,好吧,我不得不说,那个The Django Book 我只看了下前面的7章,而且还不认真.<http://djangobook.py3k.cn/2.0>
from django.conf.urls import include, url from django.contrib import admin from log import views from django.conf import settings urlpatterns = [ url(r\'^admin/\', include(admin.site.urls)), url(r\'^$\',views.login), url(r\'^login/$\',views.login), url(r\'^loginsuccess/$\',views.loginsuccess), url(r\'^logout/$\',views.logout), ]
log/views.py--------现在目前还没有加上一些判断之类的.比较菜.只是简单的.
from django.shortcuts import render from django.shortcuts import render_to_response from django.http import HttpResponse,Http404 from django import forms from django.contrib import auth from django.http import HttpResponseRedirect import datetime from django.contrib.admin import widgets import subprocess import os.path import fupy #From Post #from django.template import RequestContext class loginForm(forms.Form): username = forms.CharField(max_length=30) password = forms.CharField(widget=forms.PasswordInput) class searchForm(forms.Form): searchform = forms.CharField(label="Please Enter Search Content",min_length=1) day = forms.DateTimeField(label=\'Please Enter Log Date\',widget=widgets.AdminDateWidget()) def login(request): if request.user.is_authenticated(): return HttpResponseRedirect("/loginsuccess/") error = False if request.method == \'POST\': form = loginForm(request.POST) if form.is_valid(): username = request.POST.get(\'username\',\'\') password = request.POST.get(\'password\',\'\') user = auth.authenticate(username=username,password=password) if user is not None and user.is_active: auth.login(request,user) return HttpResponseRedirect("/loginsuccess/") else: error=True #return HttpResponse("not user") else: form = loginForm() return render_to_response(\'login.html\',{\'form\':form,\'error\':error}) def loginsuccess(request): if request.user.is_authenticated(): if request.method == \'POST\': searchform = searchForm(request.POST) if searchform.is_valid(): searchtext = searchform.cleaned_data[\'searchform\'] today = searchform.cleaned_data[\'day\'] today_day = str(today.day).zfill(2) #print today_day #print searchtext if \'|\' in searchtext: searchtext_error = True return render_to_response(\'search.html\',{\'form\':searchform,\'searchtext_error\':searchtext_error,\'uname\':request.user}) logpath = os.path.join(\'/home/var/log/\',str(today.year),str(today.month),today_day) if not os.path.exists(logpath): file_error = True return render_to_response(\'search.html\',{\'form\':searchform,\'file_error\':file_error,\'uname\':request.user}) logpath = os.path.join(logpath,\'*\') cmd = "sudo grep \'%s\' %s"%(searchtext,logpath) print cmd showlog = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE) text = showlog.communicate() textshow = text[0].split(\'\n\') textshow2 = fupy.returnShowLog(textshow) return render_to_response(\'search.html\',{\'showlog\':textshow2,\'form\':searchform,\'uname\':request.user}) else: searchform = searchForm( initial={\'day\':datetime.datetime.now().strftime("%Y-%m-%d")} ) return render_to_response(\'search.html\',{\'form\':searchform,\'uname\':request.user}) else: return HttpResponseRedirect("/login/") def logout(request): auth.logout(request) return render_to_response("logout.html")
log/templates/base.html-----html模板文件,这里主要是导入bootstrap文件.其它的就没有什么了.
1 {% load staticfiles %} 2 <!DOCTYPE html> 3 <html> 4 <head> 5 <meta charset="utf-8" /> 6 {% block title %}<title>Searchlog</title>{% endblock %} 7 <!-- <script src="{% static \'bootstrap/js/jquery.ui-1.9.0.min.js\' %}"></script> --> 8 <script src="{% static \'bootstrap/js/jquery.min.js\' %}"></script> 9 <!-- 引入 Bootstrap --> 10 <link href="{% static \'bootstrap/css/bootstrap.min.css\' %}" rel="stylesheet"> 11 <script src="{% static \'bootstrap/js/html5shiv.js\' %}"></script> 12 <script src="{% static \'bootstrap/js/respond.min.js\' %}"></script> 13 <script type="text/javascript" src="{% static \'bootstrap/js/bootstrap.js\' %}"></script> 14 <style type="text/css" src="{% static \'bootstrap/css/bootstrap.css\' %}"></style> 15 </head> 16 <body> 17 {% block content %} 18 {% endblock %} 19 </body> 20 </html>
log/templates/login.html-------登陆窗口页面
1 {% extends "base.html" %} 2 {% block content %} 3 <div class="container"> 4 <div class="row"> 5 <div class="col-md-6 col-md-offset-3"> 6 {% if error %} 7 <div class="alert alert-warning alert-dismissible" role="alert"> 8 <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> 9 <strong>提示:</strong>您的账号或者密码有误,请重新进行登陆,谢谢! 10 </div> 11 {% endif %} 12 <div class="jumbotron"> 13 <form class="form-signin" role="form" method="POST" action="">{% csrf_token %} 14 <h2 class="form-signin-heading">Please sign in</h2> 15 <input class="form-control" placeholder="{{ form.username.name }}" required="" autofocus="" type="{{ form.username.name }}" name="{{ form.username.name }}"> 16 <input class="form-control" placeholder="Password" required="" type="password" name="{{ form.password.name }}"> 17 <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button> 18 </form> 19 </div> 20 </div> 21 </div> 22 </div> 23 {% endblock %}
log/templates/search.html----查询窗口页面
1 {% extends "base.html" %} 2 {% block content %} 3 <div class="container"> 4 <div class="row"> 5 <div class="col-md-12 col-md-offset-0"> 6 <h3>Hello {{ uname.username }}</h3> 7 <form method="POST" action=""> 8 {% if form.searchform.errors %} 9 <div class="alert alert-success" role="alert"> 10 <strong>警告!</strong> 请输入需要搜索的日志内容!<br> 11 </div> 12 {% endif %} 13 {% if form.day.errors %} 14 <div class="alert alert-success" role="alert"> 15 <strong>警告!</strong> 请输入搜索日志时间! 16 </div> 17 {% endif %} 18 {% if searchtext_error %} 19 <div class="alert alert-warning alert-dismissible" role="alert"> 20 <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> 21 <strong>Warning!</strong> 请搜索正确的内容!不要在搜索内容中带有“|”符号,谢谢! 22 </div> 23 <p style="color: red;"></p> 24 {% endif %} 25 {% if file_error %} 26 <div class="alert alert-warning alert-dismissible" role="alert"> 27 <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> 28 <strong>Warning!</strong> 您搜索的日期没有日志,请输入正确的日期,谢谢!格式如:2016-10-10 29 </div> 30 {% endif %} 31 <input class="form-control" placeholder="{{ form.searchform.label }}" type="text" name="{{ form.searchform.name }}" style="width:800px;"> 32 <input class="form-control" type="text" name="{{ form.day.name }}" size="10" value="{{ form.day.value }}" style="width:130px;"> 33 <!-- {{form.as_p}}--> 34 35 <!-- <input type="submit" value="searchlog"> --> 36 <button type="submit" class="btn btn-primary">Search</button> 37 <a href="/logout/">注销登陆</a><br/> 38 <hr> 39 <table class="table table-hover"> 40 <thead> 41 <th>序列</th><th>日志内容</th> 42 </thead> 43 {% for logline in showlog %} 44 <tr> 45 <td>{{ forloop.counter }}</td><td>{{ logline }}</td> 46 </tr> 47 {% endfor %} 48 </table> 49 </form> 50 </div> 51 52 </div> 53 </div> 54 {% endblock %}
恩,好吧,大概就是这样一个页面的东西了,没有什么其它的东西了!回想起来还是非常简单的,最麿人的事情是在apache+wsgi的时候,好了!那都是后话了,这样试了下,每天大概有几百M的日志,这样查没有什么问题,响应速度还是不错的。好吧,是好垃圾个,暂时时间与能力有限,先这样,后面再慢慢的进行修改优化下!!!
最新修改,为了方便日志的查看,在搜索的时候会将搜索的内容进行高亮显示,如上图。这个底层返回纠结了下子,因为要可以有星号。