目录
- 项目介绍和源码;
- 拿来即用的bootstrap模板;
- 服务器SSH服务配置与python中paramiko的使用;
- 用户登陆与session;
- 最简单的实践之修改服务器时间;
- 查看和修改服务器配置与数据库的路由;
- 基于websocket的实时日志实现;
- 查看服务器中的日志与前端的datatable的利用;
- 重启服务器进程。
前言
本篇文章会说下如何在网站上交互修改服务器的时间。其实质是通过网站调用文章服务器SSH服务配置与python中paramiko的使用中介绍的paramiko写的接口去和Linux服务器交互(图1中的函数)。网页分为获取时间,修改时间和记录修改时间三个简单功能,大体的结构如图1所示,页面效果如图2所示。也有些小细节的完善,如laydate插件的使用和通过数据库后台记录正在进行的任务等。
功能实现
关于模板简化的方法在拿来即用的bootstrap模板文章中已经实现了,文章中说到,网页独有的内容放在{% block mainbody %}
中,现在我们考虑在空空如也的模板中添加一些功能。在写之前,我们把文章中提到的各种paramiko封装的接口放在functions.py这个文件里面,并把它塞到WebTool/WebTool下面,如图3,以便解耦。
下面是一堆html代码,这段代码实现了图2所示的前端内容(其中的{{}}中内容是由下文中提到的渲染函数servertime传递上来的)。然后说下实现。
{% extends "./base.html" %}
{% block othercss %}{% 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-calendar"></i></h3>
<div class="row mt">
<div class="col-lg-6">
<div class="form-panel">
<h4 class="mb"> 服务器时间</h4>
<div class="col-sm-12">
<h4 class="mb" id="getservertime" style="text-align: center"> {{time}}</h4>
</div>
<div><br><br><br></div>
<div class="col-sm-12" style="text-align: right">
<button id="gettime" class="btn btn-theme02">重新获取</button>
</div>
<div><br><br><br></div>
</div>
</div>
<div class="col-lg-6">
<div class="form-panel">
<h4 class="mb"> 修改服务器时间</h4>
<div class="col-sm-12">
<div class="task-content">
<ul id="sortable" class="task-list ui-sortable">
{% if serverstatus == 'others' %}
<li class="list-danger">
<i class=" fa fa-ellipsis-v"></i>
<span class="task-title-sp">【{{taskor}}】在使用服务器,无法修改时间</span>
</li>
{% elif serverstatus == 'nobady' %}
<li class="list-success">
<i class=" fa fa-ellipsis-v"></i>
<input type="checkbox" class="list-child" onchange="isCheck(this)" value="">
<span class="task-title-sp" id="use"> 我在使用中,请勿修改时间</span>
</li>
{% else %}
<li class="list-success">
<i class=" fa fa-ellipsis-v"></i>
<input type="checkbox" class="list-child" checked="checked" onchange="isCheck(this)" value="">
<span class="task-title-sp" id="use"> 我在使用中,请勿修改时间</span>
</li>
{% endif %}
</ul>
</div>
</div>
<div><br><br><br><br></div>
{% if serverstatus != 'others' %}
<div class="col-sm-12" id="status">
<input type="text" class="form-control" id="time">
<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>
</div>
<div><br><br><br></div>
<div class="col-sm-12" style="text-align: right">
<button id="putsettingtime" class="btn btn-theme02">提交修改</button>
<button id="putlocaltime" class="btn btn-theme02">快捷恢复系统时间</button>
</div>
<div><br><br><br></div>
{% endif %}
</div>
</div>
</div>
<div class="row mt">
<div class="col-lg-6">
<div class="form-panel">
<h4 class="mb"> 修改时间的记录</h4>
<table class="table table-hover">
<thead>
<tr>
<th style="width:10%;">修改时间</th>
<th style="width:10%;">修改人</th>
<th style="width:10%;">修改后服务器时间</th>
</tr>
</thead>
<tbody id="tab">
{% for modifytime in modifytimes %}
<tr>
<td>{{ modifytime.modifytime }}</td>
<td>{{ modifytime.modifyer }}</td>
<td>{{ modifytime.modifyservertime }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</section>
{% endblock %}
该页面所需的完整javascript代码如下,其中已经包含了下文要实现的功能函数,包括重新获取时间、修改时间、本人占用服务器不准其他人修改时间、显示修改时间的记录,具体细节可以看代码中的注释,另外代码中的swal是sweetalert2组件,文章用户登陆与session已经提到过其引用和用法。
{% block scripts %}
<script>
// 获取并局部刷新图4蓝色框中现实的服务器时间
function getservertime(){
$.ajax({
url:"getservertime",
type:'GET',
success: function(arg){
ret = eval(arg);
if(ret.status){
$("#getservertime").html(ret.time)
}else{
$("#getservertime").html(ret.error)
}
}
});
}
// 本人是否占用服务器
function isCheck(obj){
if($(obj).prop("checked")){
$.ajax({
url:"usingserver",
type:'GET',
data:{'using':'yes'},
});
}else{
$.ajax({
url:"usingserver",
type:'GET',
data:{'using':'no'},
});
}
}
$(document).ready(function(){
// 页面载入时候就会获取一次服务器时间
$("#gettime").click(function(){
getservertime();
});
// 修改服务器时间的函数
$("#putsettingtime").click(function(){
settingtime = $("#time").val();
if(settingtime == ''){
swal('', '请选择时间!', 'error')
}
else{
swal({
title: '将服务器时间设定为输入的时间?',
type: 'warning',
confirmButtonColor: '#DD6B55',
confirmButtonText:"是的",
cancelButtonText:"不用",
showLoaderOnConfirm: true, //加载按钮是否可见
showCancelButton: true,
preConfirm: function() {
return new Promise(function(resolve) {
setTimeout(function(){
$("#putlocaltime").hide();
$("#putsettingtime").hide();
$("#time").hide();
$("#loading").show();
resolve();
}, 3000);
});
},
allowOutsideClick: false, //弹框外是否可点
}).then(function(res){
if(res){
$.ajax({
url:"settime",
type:'POST',
data:{'settime':settingtime},
success: function(arg){
ret = eval(arg);
if(ret.status){
swal({
type: 'success',
title: '时间设定完成!',
confirmButtonText: '确定',
confirmButtonColor: '#4cd964'
}).then(function(){
//修改成功之后,局部刷新图4蓝色框中的显示的时间
getservertime();
$("#putlocaltime").show();
$("#putsettingtime").show();
$("#time").show();
$("#loading").hide();
// 向前端的修改时间记录表格中添加一条记录
var tr = "<tr><td>"+ret.modifytime+"</td><td>"+ret.modifyer+"</td><td>"+ret.servertime+"</td></tr>"
$("#tab tr:first").before(tr); //向table的第一行添加数据
$("#tab tr:last").remove(); //删除最后一行
});
}else{ //修改失败
swal({
type: 'error',
title: '时间设定失败!',
confirmButtonText: '确定',
confirmButtonColor: '#4cd964'
}).then(function(){
getservertime();
$("#putlocaltime").show();
$("#putsettingtime").show();
$("#time").show();
$("#loading").hide();
});
}
}});
}
});
}
});
// 重置服务器时间
$("#putlocaltime").click(function(){
swal({
title: '将服务器时间设定为本地时间?',
type: 'warning',
confirmButtonColor: '#DD6B55',
confirmButtonText:"是的",
cancelButtonText:"不用",
showLoaderOnConfirm: true, //加载按钮是否可见
showCancelButton: true,
preConfirm: function() {
return new Promise(function(resolve) {
setTimeout(function(){
$("#putlocaltime").hide();
$("#putsettingtime").hide();
$("#time").hide();
$("#loading").show();
resolve();
}, 3000);
});
},
allowOutsideClick: false, //弹框外是否可点
}).then(function(res){
if(res) {
$.ajax({
url:"recoverlocaltime",
type:'GET',
success: function(arg){
ret = eval(arg);
if(ret.status){
swal({
type: 'success',
title: '时间设定完成!',
confirmButtonText: '确定',
confirmButtonColor: '#4cd964'
}).then(function(){
//修改成功之后,局部刷新图4蓝色框中的显示的时间
getservertime();
$("#putlocaltime").show();
$("#putsettingtime").show();
$("#time").show();
$("#loading").hide();
//修改成功之后,局部刷新图4蓝色框中的显示的时间
var tr = "<tr><td>"+ret.modifytime+"</td><td>"+ret.modifyer+"</td><td>"+ret.modifytime+"</td></tr>"
$("#tab tr:first").before(tr); //向table的第一行添加数据
$("#tab tr:last").remove(); //删除最后一行
});
}else{
swal({
type: 'error',
title: '时间设定失败!',
confirmButtonText: '确定',
confirmButtonColor: '#4cd964'
}).then(function(){
getservertime();
$("#putlocaltime").show();
$("#putsettingtime").show();
$("#time").show();
$("#loading").hide();
});
}
}});
}
});
});
// laydata组件
laydate.render({
elem: '#time',
type: 'datetime',
theme: 'molv'
});
});
</script>
// 引入laydata组件
<script src="/templates/servermaterial/assets/laydate/laydate.js"></script>
{% endblock %}
创建models.py
django自带强大的与数据库操作相关的api,使得用户在使用数据库时只用考虑存储的逻辑,django操作数据库中的一些常用函数可以查看该文章。另外,在文章查看和修改服务器配置与数据库的路由也会提到一些数据库函数的用法。
- 服务器被占用
你在操作服务器时,别人也在使用服务器,当你操作(修改时间,配置)时会被别人影响服务器环境的时候,可以考虑把服务器‘锁’起来,拿修改服务器时间举个例子,我们不想让别人通过这个网站修改服务器时间,我们可以在数据库中设置一个表,用来记录服务器的任务状态,当有用户在使用这个任务时,它会在这个表中记录一条数据,别人在需要做该任务时,会发现表中有一个相同的任务在进行,没法操作。任务完成后,表中删除对应的任务记录,别人就可以进行了(简而言之,A操作的时候B不能操作)。具体如何使用后面会说到。
对了,在初始化数据库前,需要执行python manage.py makemigrations
、python manage.py migrate
、python manage.py migrate --database=server
三条指令分别用来更新表、刷新默认的数据库和server的数据库,关于server的数据库,可以查看文章查看和修改服务器配置与数据库的路由。
class taskinbackground(models.Model):
# 任务的名字
taskname = models.CharField(max_length=50)
# 操作人
taskor = models.CharField(max_length=100)
class Meta:
# 别名
db_table = 'task'
# 数据库路由标签
app_label = "server"
- 改时间记录
class modifytime(models.Model):
# 修改人
modifyer = models.CharField(max_length=100)
# 操作时间
modifytime = models.CharField(max_length=200, default="")
# 变更后服务器时间
modifyservertime = models.CharField(max_length=200, default="")
class Meta:
db_table = 'modifytime'
app_label = "server"
显示页面
设计的时候,考虑到当用户进入http://127.0.0.1:8888/server/servertime.html网页时就能够获取时间和修改时间的记录,所以添加url和模板显示函数view,分别位于server/urls.py和server/views.py,其中server/urls.py和上文中给出javascript函数一样给出了下文中所有需要用到的功能的url,server/views.py除了给出页面显示的函数servertime之外也给出了手动通过按钮重新获取(下图4红色框)得到时间的方法getservertime功能函数。
views中的servertime用到的函数get_server_time()
可以用来访问服务器获取时间,其写在WebTool/funtions.py中,具体的函数请移步至文章服务器SSH服务配置与python中paramiko的使用。
- server/urls.py中的代码如下:
from django.conf.urls import url
import views
urlpatterns = [
url(r'^$', views.homepage),
url(r'^home', views.homepage),
# 修改时间
url(r'^settime', views.settime),
# 显示时间页面
url(r'^servertime', views.servertime),
# 按钮重新获得时间
url(r'^getservertime', views.getservertime),
# 重置时间
url(r'^recoverlocaltime', views.recoverlocaltime),
# 本人占用服务器不准他人改时间
url(r'^usingserver', views.usingserver),
# 用户登出
url(r'^userlogout', views.userlogout),
]
- server/views.py中的代码如下:
# -*- 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 servertime(request):
from WebTool.functions import get_server_time
from server import models
taskor = ''
try:
# 查看是否有人在占用服务器
taskor = models.taskinbackground.objects.get(taskname='usingtime').taskor
except Exception as e:
print e
username = request.session.get('username')
# 取出数据库后10条修改时间的数据
modifytimes = models.modifytime.objects.all()[::-1][0:10]
pagedict = {'time': get_server_time(), 'modifytimes': modifytimes, 'title': htmltitle, 'username': username}
# 本人在使用服务器
if taskor == username:
pagedict['serverstatus'] = 'self'
# 无人使用服务器
elif taskor == '':
pagedict['serverstatus'] = 'nobady'
# 其他人在使用服务器
else:
pagedict['serverstatus'] = 'others'
pagedict['taskor'] = taskor
return render_to_response('servermaterial/servertime.html', pagedict)
# 这个函数用来处理按钮【重新获取】的逻辑,请求它的url和javascipt代码已经在前面给出
def getservertime(request):
if request.method == 'GET':
ret = {'status': False, 'time': '', 'error': ''}
try:
from WebTool.functions import get_server_time
# 将时间传到前端局部刷新上图4的蓝色框中显示的时间
ret['time'] = get_server_time()
ret['status'] = True
except Exception, e:
ret['status'] = False
ret['error'] = str(e)
return JsonResponse(ret)
return JsonResponse(ret)
完成上面的代码之后我们就看可以显示服务器时间页面了。并且能够查看服务器时间,手动通过按钮查看服务器时间并且局部刷新网页上的时间显示。
修改时间
- 本人占用服务器不准其他人修改时间
控制它的javascript函数为isCheck(obj)
,url为上文中的url(r'^usingserver', views.usingserver)
。占用服务器的任务名字叫做usingtime。
# 有人使用服务器,别人无法修改时间
def usingserver(request):
ret = {'status': False}
if request.method == 'GET':
status = request.GET.get('using')
from server import models
# 我占用服务器,别人无法修改时间
if status == 'yes':
username = request.session.get('username')
models.taskinbackground.objects.filter(taskname='usingtime').delete()
models.taskinbackground.objects.create(taskname='usingtime', taskor=username)
ret['status'] = True
return JsonResponse(ret)
# 我释放服务器,别人可以修改时间
if status == 'no':
models.taskinbackground.objects.filter(taskname='usingtime').delete()
ret['status'] = True
return JsonResponse(ret)
用户访问服务器时间页面时,前端会根据后台渲染函数servertime传递的参数判断服务器使用的状态,分别是本人使用中(servertime函数中的self)、没人使用(servertime函数中的nobady)、其他人在使用(servertime函数中的others)。如下图5所示,当一个用户勾选了红框中的checkbox,其他用户会无法修改时间。前端逻辑可以直接由上文中给出的html代码看出。
- 提交修改的时间
要实现该功能,还需要在server/views.py中添加这些对应的响应函数,他们都是通过前端ajax(写在上文中的javascript函数里面)请求到后台的,同样的,用到的和服务器交互的相关paramiko函数写在WebTool/functions.py中,都已经在服务器SSH服务配置与python中paramiko的使用文章中实现。重置时间和提交修改分别对应图6中红框中的按钮。
重置时间和提交修改使用到的views函数:
# 重置时间
def recoverlocaltime(request):
if request.method == 'GET':
ret = {'status': False}
try:
from WebTool.functions import restore_server_time
from server import models
# 充值时间
restore_server_time()
# 获取本地的时间
local_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
# 获取当前的操作人
username = request.session.get('username')
# 数据库中记录本次操作
models.modifytime.objects.create(modifyer=username, modifytime=local_time, modifyservertime=local_time)
ret['status'] = True
# 将修改的记录传递到前端局部刷新添加
ret['modifytime'] = local_time
ret['modifyer'] = username
except Exception, e:
ret['status'] = False
return JsonResponse(ret)
return JsonResponse(ret)
# 提交前端给过来的时间
def settime(request):
if request.method == 'POST':
ret = {'status': False}
try:
from WebTool.functions import modify_server_time
from server import models
servertime = request.POST.get('settime')
# 修改时间
modify_server_time(servertime)
# 获取本地时间
local_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
# 获取操作人
username = request.session.get('username')
# 数据库中记录改时间的记录
models.modifytime.objects.create(modifyer=username, modifytime=local_time, modifyservertime=servertime)
# 将操作的时间、服务器的时间、操作人传到前端局部添加
ret['modifytime'] = local_time
ret['servertime'] = servertime
ret['modifyer'] = username
ret['status'] = True
except Exception, e:
ret['status'] = False
return JsonResponse(ret)
return JsonResponse(ret)
- laydate组件
组件的引入和sweetalert2的引入方法一样,将laydate组件的资源文件下载下来放到资源文件夹中,然后在前端模板中引用即可,由于基本是本页面私有的资源,我们把它放到servertime.html文件中的{% block scripts %}中(可以由上文给出的该页面完整的javascript代码看到)
引用完成后,我们可以看到点击input框之后的效果如图8所示,当然laydate组件支持更多定制,可以参考这里。选好自己的样式后修改图7中的laydate.render的字段就可以了。
结语
本篇文章主要介绍了如何实现修改服务器时间等相关功能,顺带说了下如何在数据库记录任务的状态和相关前端组件的应用。写的有点乱,等把项目搭完就会把网站的源码包贴出来。