django 实现linux运维管理平台
概述
详细
一、准备工作
1、需要准备什么环境
我是在自己的云服务上编写和运行的,centos7.2的环境,python是系统自带的python2.7.5,django安装的1.8.5版本的。数据库使用的mysql5.6版本的,rrdtool版本是rrdtool-1.4.8。
2、本例子实现什么功能
①、用户管理
②、资产信息添加和展示
③、服务器性能监控
④、服务器批量管理
⑤、日志管理
⑥、经验总结编辑和展示
3、django工作原理图:
4、运维管理平台的功能模块图:
5、功能模块介绍:
(1)用户登录注册模块
用户登录注册模块包含注册、登录和注销登录的功用。这个模块主要是负责用户注册和登录运维管理系统,用户通过点击注册按钮,页面会跳转到注册页面上,用户按照页面的输入提示框,输入相应的信息完成注册,当用户输入的用户已经被注册了,那么这个时候系统会做出判断,并且给出用户提示,如果注册的用户,之前并没有注册,那么这个时候可以成功注册,并且会有提示给用户。这个时候,用户能够点击登录按钮跳转到登录页面,使用注册成功的账号和密码完成登录操作。
(2)Web页面执行Linux命令
WEBSSH功能模块是实现在web系统上操作Linux服务器。用户在首页面上点击WEBSSH按钮页面会跳转到WEBSSH命令执行页面,用户在命令输入提示框中输入格式正确的Linux命令,系统会对用户给出的命令在服务器上执行,并且把执行输出时间和执行结果展示出来。这样方便对Linux服务器进行一些常规操作。
(3)服务器资产信息管理功能
服务器资产信息管理有两个小的子功能:服务器资产信息后台编辑,用户可以在后台编辑页面上对服务器资产信息进行增加修改和删除操作。服务器信息前端展示,通过把前面通过后台编辑页面写入到数据库里面的信息,再把数据从数据库里面取出来并格式化输出给用户看。
(4)服务器性能监控模块
服务器性能监控模块是利用RRDTOOL开源软件,针对我自己写的自定义监控脚本,把磁盘、内存、cpu的性能指标数据存入RRDTOOL文件中,然后利用RRDTOOL自身的绘图功能把性能指标的数据生成图片,用户通过访问相应的按钮,在后端会执行相应的操作,实时的把1分钟、3分钟、5分钟的数据展示出来。这样用户可以查看实时的性能指标。
(5)产品上线模块
产品上线模块是针对运维常做的操作而实现的,通过点击测试环境或者正式环境的发布可以进行程序的更新和回滚操作。这样可以简化日常运维工作人员的操作负责性。
(6)服务器批量管理模块
服务器批量管理模块可以实现文件的批量同步和程序的批量管理。文件批量同步的话,为了保持大量的服务器的关键文件的一致性,所以我们需要的是在一台有主控性的服务器上修改文件,再把文件同步到后端的大批量的服务器上。这样管理十台、100台、1000台相同业务的服务器的话,事实上跟管理一台服务器是一样的。再来说一下程序的批量管理,其实和上面的思想相同,前面的文件是为了程序服务的,再者说程序也是文件,当我们把一些文件修改以后进行同步这个时候其实是为了程序做支持工作。我们通过项目来决定不同的主机组然后针对这个主机组做统一的程序管理。
(7)生产经验总结模块
生产经验总结模块可以分为三部分:文章内容的后台编辑、疑难问题展示、心得体会展示。文章后台编辑的话我真的疑难问题和心得体会各创建一个数据库表,这样的话,不管是我针对文章的编辑还是前端 页面的展示的话都会相对来更好实现和管理。用户可以把自己在工作中遇到的问题和自己的一些总结针对不同的数据库表进行编辑,然后通过前端的页面,把它们展示出来。这样的话,我们在工作中碰到一定问题的时候可以先从运维管理系统上查一下,看看之前是不是已经有人碰到过这种情况。而且通过别人的总结我们可以学习到更多宝贵的经验。
(8)日志管理模块
日志管理模块针对Linux系统产生的日志和应用程序自身产生的日志进行过滤加工处理操作,因为对我们来说日志包含很多宝贵的信息,我们可以针对我们想要了解的对于海量的日志做处理操作,然后只获取我们想要的,通过页面把我们后台处理以后的日志信息展示出来,
二、程序实现
1、用户登录
模板(templates)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | < body id="login"> < div class="login-logo"> <!--a href="index.html">linux 运维管理平台<!--img src="{% static "images/logo.png" %}" alt=""/--> </ a-- > </ div > < h2 class="form-heading">< font size="15" face="Cicle">Linux运维管理平台登录页面</ font ></ h2 > < div class="app-cam"> {{ nopass }}{{ deltxt }} < form action="/login/" method="post"> {% csrf_token %} < input type="text" class="text" value="username" name="username" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = 'username';}"> < input type="password" value="password" name="password" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = 'password';}"> < div class="submit">< input type="submit" onclick="myFunction()" value="登录"></ div > < div class="login-social-link"> < a href="/login/" class="facebook"> 登录取消 </ a > < a href="/register/" class="twitter"> 用户注册 </ a > </ div > <!--ul class="new"> <li class="new_left"><p><a href="#">忘记密码</a></p></li> <li class="new_right"><p><a href="/register/"> 注册</a></p></li> <div class="clearfix"></div> </ul--> </ form > </ div > < div class="copy_layout login"> < p >Copyright © 付炜超Linux运维管理系统登录界面 </ p > </ div > </ body > |
视图(views)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def login(request): if request.method = = 'POST' : username = request.POST.get( "username" ,"") password = request.POST.get( "password" ,"") user = User.objects. filter (username__exact = username,password__exact = password) if user: #如果用户匹配成功 response = HttpResponseRedirect( '/index/' ) #重定向到index response.set_cookie( 'cookie_username' ,username, 36 ) #设置cookie return response #把index页面输出 else : nopass = "用户名或者密码输入错误" #没有匹配成功 return render(request, 'login.html' ,{ 'nopass' :nopass}) return HttpResponse( 'yes' ) return render(request, 'login.html' ) |
模型(models)
1 2 3 4 5 6 | class User(models.Model): username = models.CharField(max_length = 30 ) password = models.CharField(max_length = 30 ) def __unicode__( self ): return self .username |
路由(url)
1 | url(r '^login/$' , 'monitor.views.login' ), |
2、用户注册
模板(templates)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | < body id="login"> < div class="login-logo"> <!--a href="index.html"><img src="{%static "images/logo.png"%}" alt=""/></a--> </ div > < h2 class="form-heading">< font size="15" face="Cicle">Linux运维管理平台注册页面</ font > </ h2 > < form class="form-signin app-cam" action="/register/" method="post">{% csrf_token %} < p > {{ registusername }} {{ registered }}</ p > < p > {{ registAdd }} {{ Registered }}</ p > < p > 请输入您的想要注册的账号和密码</ p > < input type="text" class="form-control1" placeholder="username" name="username" autofocus=""> < input type="password" class="form-control1" placeholder="password" name="password" > < label class="checkbox-custom check-success"> </ label > < button class="btn btn-lg btn-success1 btn-block" type="submit">Submit</ button > < div class="registration"> Already Registered. < a class="" href="/login/"> Login </ a > </ div > </ form > < div class="copy_layout login register"> < p >Copyright © 付炜超运维管理系统的注册页 </ p > </ div > </ body > |
视图(views)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def register(request): if request.method = = 'POST' : username = request.POST[ 'username' ] password = request.POST[ 'password' ] try : registusername = User.objects. filter (username = username).get().username registered = "已经注册了" return render(request, 'register.html' ,{ 'registusername' :registusername, 'registered' :registered}) except : registAdd = User.objects.create(username = username,password = password) Registered = "注册成功!!!" return render(request, 'register.html' ,{ 'registAdd' :registAdd, 'Registered' :Registered}) else : return render(request, 'register.html' ) return render(request, 'register.html' ) |
3、用户注销
视图(views)
1 2 3 4 | def logout(request): return render(request, 'login.html' ) response.delete_cookie( 'cookie_username' ) #删除cookie_username对应的用户的cookie return response |
4、服务器资产信息
视图(templates)
1 2 3 | def infor(request): infor_list = Information.objects. all () return render_to_response( 'information.html' ,{ 'infor_list' :infor_list}) |
模型(models)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from django.db import models class Information(models.Model): name = models.CharField(max_length = 30 ) privateip = models.GenericIPAddressField() publicip = models.GenericIPAddressField() use = models.TextField() zoneid = models.CharField(max_length = 30 ) cpu = models.CharField(max_length = 50 ) memory = models.CharField(max_length = 50 ) datadisk = models.CharField(max_length = 30 ) time = models.DateTimeField() def __unicode__( self ): return self .name |
admin
1 2 3 4 | class InformationAdmin(admin.ModelAdmin): list_display = ( 'name' , 'privateip' , 'publicip' , 'use' , 'zoneid' , 'cpu' , 'memory' , 'datadisk' ) admin.site.register(Information,InformationAdmin) |
模板(templates)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | {% block content %} < table border="1"> < tr > < th >服务器主机名</ th > < th >服务器内网ip</ th > < th >服务器公网ip</ th > < th >服务器zoneid</ th > < th >服务器cpu个数</ th > < th >服务器内存大小</ th > < th >服务器数据盘大小</ th > < th >服务器信息记录时间</ th > < th >服务器用途</ th > </ tr > {% for infor in infor_list %} < tr > < td >{{ infor.name }}</ td > < td >{{ infor.privateip}} </ td > < td >{{ infor.publicip}} </ td > < td >{{ infor.zoneid}} </ td > < td >{{ infor.cpu}} </ td > < td >{{ infor.memory}} </ td > < td >{{ infor.datadisk}} </ td > < td >{{ infor.time}} </ td > < td > {{ infor.use}}</ td > </ tr > {% endfor %} {% endblock %} |
5、服务器性能监控
视图(views)
1 2 3 4 5 6 7 8 9 10 11 12 13 | def servers(request): if request.method = = 'POST' : hostgroup = request.POST.get( "hostgroup" ,"") model = request.POST.get( "model" ,"") user = request.POST.get( "user" ,"") command = request.POST.get( "command" ,"") os.environ[ 'hostgroup' ] = str (hostgroup) os.environ[ 'model' ] = str (model) os.environ[ 'user' ] = str (user) os.environ[ 'command' ] = str (command) output = commands.getoutput( "sh /home/zqxt_form2/monitor/ansible.sh $hostgroup $model $user $command" ) return render(request, 'servers.html' ,{ 'output' :output}) return render(request, 'servers.html' ) |
模板(templates)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | < section id="content"> < div class="zerogrid"> < div class="row block"> < div class="main-content"> < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/cpu1.jpg" %}"/> < h2 >< a href="#">cpu 1 分钟的性能图</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/cpu3.jpg" %}"/> < h2 >< a href="#">cpu 3 分钟的性能图</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/cpu5.jpg" %}"/> < h2 >< a href="#">cpu 5 分钟的性能图</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/memory1.jpg" %}"/> < h2 >< a href="#">内存 1 分钟的使用图</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/memory3.jpg" %}"/> < h2 >< a href="#">内存 3 分钟的使用图</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/memory5.jpg" %}"/> < h2 >< a href="#">内存 5 分钟的使用图</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/disk1.jpg" %}"/> < h2 >< a href="#">磁盘 1 分钟的空闲量</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/disk3.jpg" %}"/> < h2 >< a href="#">磁盘 3 分钟的空闲量</ a ></ h2 > </ div > </ div > </ article > < article class="col-1-3"> < div class="wrap"> < div class="heading"> < img src="{% static "jpg/monitor/disk5.jpg" %}"/> < h2 >< a href="#">磁盘 5 分钟的空闲量</ a ></ h2 > </ div > </ div > </ article > </ div > </ div > </ div > </ section > |
rrdtool.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash #rrdtool create cpu.rrd --step 5 DS:cpuds:GAUGE:8:0:U RRA:AVERAGE:0.5:1:17280 RRA:MIN:0.5:1:17280 RRA:MAX:0.5:1:17280 RRA:AVERAGE:0.5:10:3456 RRA:MIN:0.5:10:3456 RRA:MAX:0.5:10:3456 RRA:AVERAGE:0.5:100:1210 RRA:MIN:0.5:100:1210 RRA:MAX:0.5:100:1210 while true ; do cpu=`vmstat 1 1 | tail -n 1 | awk '{print $15}' ` memory=` free -m | grep "Mem" | awk '{print $4+$6}' ` disk=` df -h | head -n 2 | tail -n 1 | awk '{print $5}' | awk -F '%' '{print $1}' ` rrdtool update . /cpu .rrd N:${cpu} rrdtool update . /memory .rrd N:${memory} rrdtool update . /disk .rrd N:${disk} sleep 5 done #1minute=`date --date '1 minute ago ' +%s` #3minute=`date --date '3 minute ago ' +%s` #5minute=`date --date '5 minute ago ' +%s` #rrdtool graph cpu1.jpg --step 5 -s ${1minute} -t "cpu 1 minute monitor" -v cpu DEF:cpu=./cpu.rrd:cpuds:AVERAGE LINE1:cpu#FF0000:'cpu avg' #rrdtool graph cpu3.jpg --step 5 -s ${3minute} -t "cpu 3 minute monitor" -v cpu DEF:cpu=./cpu.rrd:cpuds:AVERAGE LINE1:cpu#FF0000:'cpu avg' #rrdtool graph cpu5.jpg --step 5 -s ${5minute} -t "cpu 5 minute monitor" -v cpu DEF:cpu=./cpu.rrd:cpuds:AVERAGE LINE1:cpu#FF0000:'cpu avg' |
六、服务器批量管理
视图(models)
1 2 3 4 5 6 7 8 9 10 11 12 13 | def servers(request): if request.method = = 'POST' : hostgroup = request.POST.get( "hostgroup" ,"") model = request.POST.get( "model" ,"") user = request.POST.get( "user" ,"") command = request.POST.get( "command" ,"") os.environ[ 'hostgroup' ] = str (hostgroup) os.environ[ 'model' ] = str (model) os.environ[ 'user' ] = str (user) os.environ[ 'command' ] = str (command) output = commands.getoutput( "sh /home/zqxt_form2/monitor/ansible.sh $hostgroup $model $user $command" ) return render(request, 'servers.html' ,{ 'output' :output}) return render(request, 'servers.html' ) |
模板(templates)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | < h1 >批量管理页面</ h1 > < div class="login-01"> < form action="/servers/" method="post"> {% csrf_token %} < ul > < li class="first"> < a href="#" class=" icon email"></ a >< input type="text" class="text" value="主机组" name="hostgroup" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = '主机组';}" > < div class="clear"></ div > </ li > < li class="first"> < a href="#" class=" icon email"></ a >< input type="text" class="text" value="模块名" name="model" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = '模块名';}" > < div class="clear"></ div > </ li > < li class="first"> < a href="#" class=" icon email"></ a >< input type="text" class="text" value="用户" name="user" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = '用户';}" > < div class="clear"></ div > </ li > < li class="first"> < a href="#" class=" icon phone"></ a >< input type="text" class="text" value="命令" name="command" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = '命令';}" > < div class="clear"></ div > </ li > <!--li class="second"> <a href="#" class=" icon msg"></a><textarea value="Message" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = 'Comments';}">{{ output}}/textarea> <div class="clear"></div> </li--> </ ul > < input type="submit" onClick="myFunction()" value="Submit" > < div class="clear"></ div > </ form > </ div > < div class="login-01"> < form > < li class="second"> < a href="#" class=" icon phone"></ a >< textarea value="Message" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = '命令输出结果';}">{{ output }}</ textarea > < div class="clear"></ div > </ li > </ form > </ div > |
ansible.sh
1 2 | #!/bin/bash ansible $1 -m $2 -a "sudo su - '$3' -c '$4'" |
三、运行效果
程序运行:python manage.py runserver 0.0.0.0:8080
访问:http:/你服务器的ip:8080/
效果图展示:
注册页面:
登录:
首页面:
资产编辑:
监控页面:
服务器批量管理:
四、文件截图
五、其他补充
1、用于生产环境有哪些需要改善的地方
django需要配置nginx和uwsgi进行部署
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?