项目简介:
项目介绍:自动化运维是未来的趋势,最近学了不少东西,正好通过这个小项目把这些学的东西串起来,练练手。
基础架构:
- 服务器端:web框架-Django
- 前端:html css jQuery bootstrap
- 脚本:shell
- 适用系统:redhat5.8/redhat6.6
平台已实现功能:
- 中间件和数据库软件的启停和状态检查 (tomcat,nginx,apache,oracle,mysql)
完整功能设计图:
效果图:
架构图(简要):
项目源码:https://github.com/SwimBalance/autoops4
shell脚本
#!/bin/sh
#Filename:starttomcat.sh
#需要传入参数:$ $ $
# $:tomcat的home目录
# $:端口号
# $:启动tomcat超时时长
#输出结果说明:
# :启动成功
# :启动超时 #写日志函数
log(){
echo `date +"%F %T"`" "$* >> /logs/tomcat.log
} #开启tomcat函数
starttomcat(){
log "[command]:"$" [parameters]:"$*
#启动tomcat前需要调用checktomcat获取tomcat状态
status=`. /operation/tomcat/checktomcat.sh $ $`
#如果tomcat处于运行状态,就不必再启动,把状态信息返回前端
if [ $status -eq ];then
echo
#如果tomcat未运行,执行启动操作
else
su - tomcat -c $/bin/startup.sh >/dev/null >&
#设置count计时
count=
#每5秒检查一次tomcat状态,直到检查到tomcat成功启动或者超时
status=`. /operation/tomcat/checktomcat.sh $ $`
until [ $status -eq ] || [ $count -ge $ ]
do
sleep
let count=$count+
status=`. /operation/tomcat/checktomcat.sh $ $`
done
#如果检测到tomcat正常,判断为启动成功,返回状态信息
if [ $status -eq ];then
echo
#如果超时还未启动成功,则判断为启动超时,返回启动超时代号104
else
echo
fi
fi
} starttomcat $ $ $
views.py:tomcat操作响应函数
# 针对tomcat服务器的操作:
# 1.首先通过前台获得ID 和 操作
# 2.通过ID 丰富信息
# 3.形成完整的操作SQL
# 4.执行SQL,返回结果
# 5.将操作信息及结果写入操作记录表,并将结果返回前台
# 6.前台收到信息更新tomcat现在运行状态
def operation(request):
# 获得前台信息
tomcat_id = request.GET.get('id')
tomcat_action = request.GET.get('action')
oper = request.COOKIES.get('loginname')
# 根据ID和action 获得任务信息,并形成完整的操作SQL,都存入taskinfo中
taskinfo = get_taskinfo(tomcat_id, tomcat_action, oper)
# 传入taskinfo,执行SQL操作,返回目标服务器控制台的结果
mytask = Task(taskinfo)
result = mytask.execute()
if result.isdigit():
taskinfo['resulut'] = result
else:
taskinfo['resulut'] = ''
# 将操作记录写入记录表中,同时更新tomcatdata表中的状态字段
genrecords_updatestatus(taskinfo)
# 将结果传到前台
message = {
'': 'Tomcat正常运行.',
'': 'Tomcat异常,请人工检查.',
'': 'Tomcat服务关闭.',
'': 'Tomcat启动超时.',
'': 'Tomcat关闭超时.',
}
return JsonResponse({
'status': taskinfo['resulut'],
'message': message[taskinfo['resulut']],
}) # 根据ID生成taskinfo
def get_taskinfo(tomcat_id, tomcat_action, oper):
with connection.cursor() as cursor:
cursor.execute(
'SELECT id, tomcatport, tomcathome, ipaddress, startwait, stopwait FROM tomcatdata WHERE id = %s' % tomcat_id
)
tomcater = dictfetchall(cursor)[0]
serverip = tomcater['ipaddress']
cursor.execute(
"SELECT user1,password1 FROM machine_pwd WHERE ipaddress = '%s'" % serverip
)
userinfo = dictfetchall(cursor)[0]
if tomcat_action == 'check_tomcat':
tomcat_home = tomcater['tomcathome']
tomcat_port = tomcater['tomcatport']
command = 'sh /operation/tomcat/checktomcat.sh %s %s ' % (tomcat_home, tomcat_port)
elif tomcat_action == 'start_tomcat':
# 需要传入三个参数 home目录/端口号/启动超时时长
tomcat_home = tomcater['tomcathome']
tomcat_port = tomcater['tomcatport']
start_wait = tomcater['startwait']
# sh_dir = '/operation/tomcat/starttomcat.sh'
command = 'sh /operation/tomcat/starttomcat.sh %s %s %s ' % (tomcat_home, tomcat_port, start_wait)
elif tomcat_action == 'stop_tomcat':
# 需要传入三个参数 home目录/端口号/启动超时时长
tomcat_home = tomcater['tomcathome']
tomcat_port = tomcater['tomcatport']
stop_wait = tomcater['stopwait']
# sh_dir = '/operation/tomcat/starttomcat.sh'
command = 'sh /operation/tomcat/stoptomcat.sh %s %s %s ' % (tomcat_home, tomcat_port, stop_wait)
task_info = {
'id': tomcat_id,
'action': tomcat_action,
'oper': oper,
'ip': tomcater['ipaddress'],
'user': userinfo['user1'],
'pwd': userinfo['password1'],
'cmd': command,
'result': ''
}
return task_info # 写入操作记录并更新tomcat状态
def genrecords_updatestatus(taskinfo):
with connection.cursor() as cursor:
sqlstatement1 = "insert into audit_log (oper_user, oper_command, oper_message) VALUES ('%s', '%s', '%s')" % (
taskinfo['oper'], taskinfo['cmd'], taskinfo['resulut'])
sqlstatement2 = "update tomcatdata set status = %d where id = %r" % (int(taskinfo['resulut']), taskinfo['id'])
cursor.execute(sqlstatement1)
cursor.execute(sqlstatement2)
Task类
import paramiko class Task(object):
def __init__(self, task_info):
self.task_info = task_info def create_connect(self):
# 创建SSH对象
connectObj = paramiko.SSHClient()
# 把要连接的机器添加到known_hosts文件中
connectObj.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
connectObj.connect(
hostname=self.task_info['ip'],
username=self.task_info['user'],
password=self.task_info['pwd'],
port=22,
timeout=10
)
# 判断是否连接成功
###################
return connectObj def execute(self):
try:
connectObj = self.create_connect()
except:
return ''
cmd = self.task_info['cmd']
stdin, stdout, stderr = connectObj.exec_command(cmd)
result = stdout.read()
connectObj.close()
if not result:
result = stderr.read().strip()
return result.decode().strip()
js文件
$(function () {
$("ul[id='servicemgr'] li").click(function () {
<!-- 导入workPage-->
if (this.id == 'toms') {
$("#workpage").empty().load("/static/maintenance/html/workpage.html #tom_workpage");
$.ajax({
type: "GET",
url: "./../tomcatData/",
datatype: 'json',
data: {page: 1},
success: function (datas) {
loadtomcatdata(datas)
}
});
} else if (this.id == 'oras') {
$("#workpage").empty().load("/static/maintenance/html/workpage.html #ora_workpage");
$.ajax({
type: "GET",
url: "./../oracleData/",
datatype: 'json',
success: function (datas) {
loadoracledata(datas)
}
})
}
});
}); // 针对tomcat服务器的操作
function opt_tomcat(obj) {
var tomcat_mes = $("#tomcat_mes");
tomcat_mes.empty().append("正在玩命操作,请等待…");
var id = obj.id;
var action = obj.name;
$.ajax({
type: 'Get',
url: './../operation',
data: {'id': id, 'action': action},
success: function (data) {
tomcat_mes.empty().append(data['message']);
//更新状态
if (data['status'] == '101') {
$(obj).parent().prevAll('.status').children('span').attr('class', 'glyphicon glyphicon-ok-sign')
} else if (data['status'] == '102' || data['status'] == '104' || data['status'] == '105') {
$(obj).parent().prevAll('.status').children('span').attr('class', 'glyphicon glyphicon-exclamation-sign')
} else if (data['status'] == '103') {
$(obj).parent().prevAll('.status').children('span').attr('class', 'glyphicon glyphicon-remove-sign')
}
}
})
}
// 分页
function page(obj) {
var page_number = $(obj).text();
$.ajax({
type: "GET",
url: "./../tomcatData/",
datatype: 'json',
data: {page: page_number},
success: function (datas) {
loadtomcatdata(datas)
}
});
}
//导入tomcat数据
function loadtomcatdata(datas) {
var text = $('.text');
text.empty();
var html = '';
for (var i = 0; i < datas.length; i++) {
var id = datas[i]['id'];
var ip = datas[i]['ipaddress'];
var host = datas[i]['machine'];
var dec = datas[i]['description'];
var status = datas[i]['status'];
html += '<tr>';
html += '<td>' + id + '</td>';
html += '<td>' + ip + '</td>';
html += '<td>' + host + '</td>';
html += '<td>' + dec + '</td>';
// html += '<td class="status">' + status + '</td>';
//更新状态
if (status == '101') {
html += '<td class="status"><span class="glyphicon glyphicon-ok-sign" aria-hidden="true"></span></td>';
} else if (status == '102' || status == '104' || status == '105') {
html += '<td class="status"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span></td>';
} else if (status == '103') {
html += '<td class="status"><span class="glyphicon glyphicon-remove-sign" aria-hidden="true"></span></td>';
}
html += '<td>' + '<button id=' + id + ' onclick="opt_tomcat(this)" name="check_tomcat" class="btn btn-default" data-toggle="modal" data-target="#myModal">';
html += '<span class="glyphicon glyphicon-check" aria-hidden="true"></span></button></td>';
html += '<td>' + '<button id=' + id + ' onclick="opt_tomcat(this)" name="start_tomcat" class="btn btn-default" data-toggle="modal" data-target="#myModal">';
html += '<span class="glyphicon glyphicon-play" aria-hidden="true"></span></button></td>';
html += '<td>' + '<button id=' + id + ' onclick="opt_tomcat(this)" name="stop_tomcat" class="btn btn-default" data-toggle="modal" data-target="#myModal">';
html += '<span class="glyphicon glyphicon-stop" aria-hidden="true"></span></button></td>';
html += '</tr>';
}
text.append(html); }
//搜索栏
function searchtomcat() { var search_val = $('#search_tom').val();
$.ajax({
type: "GET",
url: "/../searchtomcat/",
data: {'data': search_val},
datatype: "json",
success: function (datas) {
loadtomcatdata(datas);
$('#preandnext').empty()
}
})
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
{% load static %}
<title>自动化运维</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入 Bootstrap -->
<link href="{% static 'maintenance/bootstrap3.3.7/css/bootstrap.min.css' %}" rel="stylesheet">
<meta charset="UTF-8">
<!-- 导入Jquery文件-->
<script src="{% static 'maintenance/js/jquery-3.2.1.min.js' %}"></script>
<!--导入bootstrap中的js 插件-->
<script src="{% static 'maintenance/bootstrap3.3.7/js/bootstrap.min.js' %}"></script>
<!--导入自己的js文件-->
<script src="{% static 'maintenance/js/show_workpage.js' %}"></script>
<style>
.glyphicon-ok-sign{color:green}
.glyphicon-exclamation-sign{color:crimson;}
.glyphicon-remove-sign{color:darkgray}
</style>
</head>
<body>
<div class=" container-fluid">
<div class="row">
<div class="col-lg-12" style="text-align:center;background-color: #9acfea">
<h3>AUTO OPERATION
<small>自动化运维平台</small>
</h3>
</div>
</div>
<div class="row ">
<div class="col-lg-2" style="margin-left :-15px;">
<ul class="nav nav-pills nav-stacked">
<li id="home" role="presentation" class="active"><a href="javascript:void(0)">主页</a></li>
<li class="active">
<a href="#servicemgr" class="nav-header collapsed " data-toggle="collapse">
<i class="glyphicon glyphicon-cog"></i>服务管理
<span class="pull-right glyphicon glyphicon-chevron-toggle"></span>
</a>
<ul id="servicemgr" class="nav nav-list collapse in" style="list-style: none">
<li id="oras" role="presentation"><a href="javascript:void(0)">Oracle服务管理</a></li>
<li id="mysqls" role="presentation"><a href="javascript:void(0)">MySQL服务管理</a></li>
<li id="toms" role="presentation"><a href="javascript:void(0)">Tomcat服务管理</a></li>
<li id="apache" role="presentation"><a href="javascript:void(0)">Apache服务管理</a></li>
<li id="nginx" role="presentation"><a href="javascript:void(0)">NGINX服务管理</a></li>
</ul>
</li>
<li class="active">
<a href="#systemsetting" class="nav-header collapsed " data-toggle="collapse">
<i class="glyphicon glyphicon-cog"></i>系统管理
<span class="pull-right glyphicon glyphicon-chevron-toggle"></span>
</a>
<ul id="systemsetting" class="nav nav-list collapse in">
<li class="active"><a href="#"><i class="glyphicon glyphicon-user"></i> 用户信息维护</a></li>
<li><a href="javascript:void(0)"><i class="glyphicon glyphicon-th-list"></i> 应用系统信息维护</a></li>
<li><a href="javascript:void(0)"><i class="glyphicon glyphicon-asterisk"></i> 服务器信息维护</a></li>
<li><a href="javascript:void(0)"><i class="glyphicon glyphicon-eye-open"></i> 日志查看</a></li>
</ul>
</li>
</ul>
</div>
<div class="col-lg-10">
<div id="workpage"></div>
<!-- 模态框(Modal) -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">操作结果</h4>
</div>
<div class="modal-body" id="tomcat_mes"></div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal -->
</div>
</div>
</div>
<div class="page-footer"></div>
</div> </body>
</html>
workpage.html
<!-- tomcat工作页-->
<div id="tom_workpage">
<div style="border: 1px;">
<div class="row">
<ol class="breadcrumb">
<li><a href="#">Home</a></li>
<li class="active">Tomcat</li>
</ol>
<div class="row">
<div class="col-lg-6" style="float: right">
<div class="input-group">
<input id="search_tom" type="text" class="form-control" placeholder="IP/服务器名称" onkeydown="if(event.keyCode==13) {searchtomcat()}">
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="searchtomcat()">查找</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
<table class="table table-hover table-condensed">
<caption><strong>Tomcat应用服务器清单</strong></caption>
<thead>
<tr>
<th>ID</th>
<th>IP</th>
<th>主机名</th>
<th>概要</th>
<th>状态</th>
<th>检查</th>
<th>开启</th>
<th>停止</th>
</tr>
</thead>
<tbody class="text"> </tbody>
</table>
</div>
<nav id="preandnext" style="text-align: center">
<ul class="pagination" style="margin: 0">
<li onclick="previousPage(this)"><a href="javascript:void(0)">«</a></li>
<li onclick="page(this)"><a href="javascript:void(0)">1</a></li>
<li onclick="page(this)"><a href="javascript:void(0)">2</a></li>
<li onclick="page(this)"><a href="javascript:void(0)">3</a></li>
<li onclick="page(this)"><a href="javascript:void(0)">4</a></li>
<li onclick="page(this)"><a href="javascript:void(0)">5</a></li>
<li onclick="nextPage(this)"><a href="javascript:void(0)">»</a></li>
</ul>
</nav>
</div>
</div>
这个小项目还会继续做下去,期望能达到当初自己设计的那样。。。。。。。