实现的细节和引用的文件和以前博客记录的基本一致
https://shaka.blog.csdn.net/article/details/106927633
差别在于,这次是通过跳板机登陆获取的主机信息,只记录差异的部份
1.需要在跳板机相应的路径放置PYTHON的脚本resc.py
resc.py这个脚本中有引用的文件(pm.sh,diskpnum.sh)和以前的记录一样,不再重复列出
这个脚本接受一个参数,IP地址,django一端的服务器将通过SSH连接,并将参数传递给脚本执行
脚本将返回包含CPU,内存,磁盘信息的字典,因为不同主机的磁盘分区名称和数量的不一致性,带有磁盘信息的这个KEY的值,将是一个LIST
# -*- coding: utf-8 -*-
import os,sys
import paramiko
import time
import sys
reload(sys)
import os
import json
import multiprocessing
import signal
sys.setdefaultencoding('utf-8')
class TimeoutException(Exception):
pass
def timeout_handler(signum, frame):
raise TimeoutException("error")
def sshreinfos(ips):
try:
redict = {}
paramiko.util.log_to_file("/yourreexecpath/paramiko.log")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
pkey = paramiko.RSAKey.from_private_key_file("/home/user/.ssh/id_rsa")
ssh.connect(hostname=ips, port=22, username='sshuser', pkey=pkey, timeout=5)
t = ssh.get_transport()
sftp=paramiko.SFTPClient.from_transport(t)
sftp.put("/yourreexecpath/pm.sh","/tmp/pm.sh")
sftp.put("/yourreexecpath/diskpnum.sh", "/tmp/diskpnum.sh")
stdindcpu, stdoutcpu, stderrcpu = ssh.exec_command("top -bn1 | awk '/Cpu/{print $2,$3,$4}' | sed 's/[a-z]//g' | sed 's/ //g' | awk -F',' '{print $1+$2+$3}'")
stdinmomeryall, stdoutmomeryall, stderrmomeryall = ssh.exec_command("free -m | awk '{print $2}' | awk 'NR==2{print}'")
stdinmomery, stdoutmomery, stderrmomery = ssh.exec_command("sh /tmp/pm.sh")
musep = (stdoutmomery.read()).replace("\n", "")
cpuusep = (stdoutcpu.read()).replace("\n", "")
memoryall = (stdoutmomeryall.read()).replace("\n", "")
remark = "正常"
try:
b = round(float(musep))
if int(b) > 80:
remark = "评估是否扩内存"
except Exception:
remark = "NONE"
redict["ips"] = ips
redict["stdoutcpu"] = cpuusep
redict["stdoutmomeryall"] = memoryall
redict["musep"] = musep
redict["remark"] = remark
ymdhms = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
stdindps, stdoutdps, stderrdps = ssh.exec_command("sh /tmp/diskpnum.sh " + ymdhms)
dpnums = (stdoutdps).read().replace("\n", "")
# print "1.5$"
sftp.get("/tmp/diskusetmp" + ymdhms + ".txt", "/yourreexecpath/"+ips + "diskusetmp" + ymdhms + ".txt")
diskinfos = open("/yourreexecpath/"+ips + "diskusetmp" + ymdhms + ".txt", 'r')
disklists = []
for lines in diskinfos:
diskitems = {}
cons = lines.split()
diskitems["pt"] = cons[0].strip()
diskitems["pttotal"] = cons[1].strip()
diskitems["ptuse"] = cons[2].strip()
disklists.append(diskitems)
diskinfos.close()
os.remove("/yourreexecpath/"+ips + "diskusetmp" + ymdhms + ".txt")
redict["disklists"] = disklists
ssh.close()
return redict
except:
#print "error"
return "error"
if __name__ == "__main__":
if len(sys.argv) != 2:
print "argv must be one"
exit()
ips = sys.argv[1]
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(10) # set timeout to 10 seconds
try:
print sshreinfos(ips)
except TimeoutException:
print("error")
2.django一端的实现如下:
views.py对应的方法
用户点击不同的按钮选择是打印到WEB页面,还是打印到WEB页面+下载巡检报告的EXCEL表格
request.POST.has_key('chkaproc')或request.POST.has_key('chkonlylists')
def chkosinfos(request):
if request.method=="POST":
sqlstr = request.POST.get("sqlstr")
filenames=""
if request.POST.has_key('chkaproc'):
try:
import f5.sysinfos
#filenames,relists=f5.sysinfos.receivewebsqlstr(sqlstr)
relists=f5.sysinfos.remoterelists(sqlstr)
filenames=f5.sysinfos.remotereexcel(relists)
except Exception:
return render(request,"exportsysinfos.html",{"login_err":"SYSINFOSFAILSTEP1"})
return render(request,"exportsysinfos.html",{"login_err":"downloadlink:http://web服务器IP地址(存放文件用,程序将文件生成到指定的web虚拟目录):9999/"+filenames,"templist":relists})
if request.POST.has_key('chkonlylists'):
try:
import f5.sysinfos
relists=f5.sysinfos.remoterelists(sqlstr)
except Exception:
return render(request,"exportsysinfos.html",{"login_err":"SYSINFOSFAILSTEP1"})
return render(request,"exportsysinfos.html",{"login_err":"OKAY"+filenames,"templist":relists})
else:
return render(request,"exportsysinfos.html",{"login_err":"no set"})
views.py引用的两个方法
remoterelists返回多个服务器巡检信息的list
remotereexcel将信息写入excel
# -*- coding: utf-8 -*-
import os,sys
#sys.setdefaultencoding('utf8')
import paramiko
import xlsxwriter
import time
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from multiprocessing import Process,Manager
import multiprocessing
import os
import json
def sshconn():
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#ssh.connect(hostname=self.f5ips, port=22, username=self.usernames, password=self.passwords)
pkey = paramiko.RSAKey.from_private_key_file("D:\\idrsapath\\id_rsa")
ssh.connect(hostname="serveripaddress", port=22, username='sshuser', pkey=pkey, timeout=5)#连接跳板机
return ssh
except Exception:
return "error"
def remoterelists(sqlstrs):
relists=[]
iplists = []
for line in sqlstrs.splitlines():
con = line.split()
names = con[0].strip()
iplists.append(names)
try:
ssh=sshconn()
for ips in iplists:
print ips
start_time = time.time()
try:
stdindcmd, stdoutcmd, stderrcmd=ssh.exec_command("/usr/bin/python /yourreexecpath/resc.py " + ips)
ipsdict=stdoutcmd.read().replace("\n", "")#.decode('utf-8')
end_time = time.time()
if end_time - start_time > 10:
continue
if ipsdict != "error":
relists.append(eval(ipsdict))
except:
print "error remotecmds"
pass
ssh.close()
return relists
except:
print "connect sshserver error"
return "error"
def remotereexcel(excellists):
nowtime=time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time()))+""
filenames=nowtime+'systeminfo.xlsx'
workbook1 = xlsxwriter.Workbook(".\\uploads\\"+filenames)
worksheet = workbook1.add_worksheet()
t1='服务器运行情况'
format=workbook1.add_format()
#worksheet.set_column(0,15,20)
format.set_bold()
yellow=workbook1.add_format({'align':'center','valign':'vcenter','font_size':22,'fg_color':'FFC1C1'})
yellow.set_bold()
# worksheet.merge_range(0,0,0,4,t1,yellow)
worksheet.merge_range('A1:I1',t1,yellow)
worksheet.set_row(0, 38)
worksheet.set_column("A:A",20)
worksheet.set_column("B:B",11)
worksheet.set_column("C:C",12)
worksheet.set_column("D:D",12)
worksheet.set_column("E:E",20)
title=[u'IP地址',u'CPU使用率%',u'内存总量',u'内存使用率%',u'巡检结果']
format=workbook1.add_format()
format=workbook1.add_format({'align':'center','valign':'vcenter'})
format.set_bold()
worksheet.write_row('A2',title,format)
worksheet.set_row(1, 25)
row=2
try:
for lines in excellists:
try:
worksheet.write(row,0,lines["ips"])
worksheet.write(row,1,lines["stdoutcpu"])
worksheet.write(row,2,lines["stdoutmomeryall"])
worksheet.write(row,3,lines["musep"])
remark="正常"
try:
b=round(lines["musep"])
if int(b)>80:
remark="评估是否扩内存"
except Exception:
remark="NONE"
worksheet.write(row,4,remark)
ymdhms=time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))
n=5
for diskpts in lines["disklists"]:
worksheet.set_column(n,n,20)
worksheet.write(row,n,"分区 "+diskpts["pt"].strip())
worksheet.set_column(n+1,n+1,20)
worksheet.write(row,n+1,"分区大小 "+diskpts["pttotal"].strip())
worksheet.set_column(n+2,n+2,20)
try:
dps=round(float(diskpts["ptuse"].strip()))
if int(dps)>80:
formatmred = workbook1.add_format({'bold': True, 'font_color': 'red'})
worksheet.write(row,n+2,"分区使用率 "+diskpts["ptuse"].strip(),formatmred)
else:
worksheet.write(row,n+2,"分区使用率 "+diskpts["ptuse"].strip())
except Exception:
worksheet.write(row,n+2,"分区使用率未获取数据")
n=n+3
except Exception:
print lines["ips"] +" error"
worksheet.write(row,0,lines["ips"])
worksheet.write(row,1,"none")
worksheet.write(row,2,"none")
worksheet.write(row,3,"none")
row=row+1
except Exception:
print "cannot get datas"
return "error"
return filenames
3.HTML页面将用户需要巡检的IP列表粘贴到输入框,一行一个IP
html的写法,不怎么会写,只是先写个实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EXPORTHISTORYVALUES</title>
</head>
<body>
<div id="container" class="cls-container">
<div id="bg-overlay" ></div>
<div class="cls-header cls-header-lg">
<div class="cls-brand">
<h3>主机巡检并导出信息</h3>每行一个IP
</div>
</div>
<div class="cls-content">
<div class="cls-content-sm panel">
<div class="panel-body">
<form id="loginForm" action="{% url 'chkosinfos' %}" method="POST"> {% csrf_token %}
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-user"></i></div>
<textarea type="text" class="form-control" name="sqlstr" placeholder="主机巡检并导出信息,每行一个IP" style="width:600px;height:111px"></textarea></br>
</div>
</div>
</br></br>
<button class="btn btn-success btn-block" type="submit" name="chkaproc">
<b>CHK+EXCEL下载链接</b>
</button>
</br></br>
<button class="btn btn-success btn-block" type="submit" name="chkonlylists">
<b>CHK不需要EXCEL,仅网页展示</b>
</button>
<h4 style="color: #ff0000"><b>{{ login_err }}</b></h4>
{% for row in templist %}
<td>IP:{{ row.ips }}</td></br>
<td><div style="color:{% if row.stdoutcpu|floatformat:"0"|add:"0" >= 50 %}red{% else %}black{% endif %}">CPU使用率:{{ row.stdoutcpu }}</div></td></br>
<td>内存总量M:{{ row.stdoutmomeryall }}</td></br>
<td><div style="color:{% if row.musep|floatformat:"0"|add:"0" >= 90 %}red{% else %}black{% endif %}"> 内存使用率:{{ row.musep }} </div> </td></br>
{% if 'disklists' in row %}
{% for diskrows in row.disklists %}
<td><div style="color:{% if diskrows.ptuse|floatformat:"0"|add:"0" >= 90 %}red{% else %}black{% endif %}"> 分区名称:{{ diskrows.pt }} 分区容量:{{ diskrows.pttotal }} 分区
{# <h4 style="color: red"><b>{{ login_err }}</b></h4>#}
</form>
</div>
</div>
</div>
</div>
</body>
</html>