服务器数据采集与接收
采集数据可以有n种方法。但是我们并不需要太高深的知识,python基础足矣。现在完成的是一个Python获取linux服务器资源的脚本。
#!/usr/bin/env python3
#coding:utf-8
import os
import uuid
import socket
#获取主机名
hostname = socket.gethostname()
#获取ip地址,不确定获取那个
ip = socket.gethostbyname(hostname)
#mac地址
mac = uuid.UUID(int = uuid.getnode()).hex[-12:].upper()
mac = ":".join([mac[i:i+2] for i in range(0,11,2)])
#cpu型号
with os.popen("cat /proc/cpuinfo") as f:
for line in f.readlines():
key,value = line.split(":")
key = key.strip()
value = value.strip()
if key == "model name":
cpuData = value
break
#内存大小
with os.popen("cat /proc/meminfo") as f:
for line in f.readlines():
key,value = line.split(":")
key = key.strip()
value = value.strip()
if key == "MemTotal":
MemTotal = value
break
print(MemTotal)
效果如下:
but,上面的方法没有将数据进行统筹,所以我们需要将数据进行一次整合
#!/usr/bin/env python3
#coding:utf-8
import os
import uuid
import socket
result = {}
#获取主机名
hostname = socket.gethostname()
result["hostname"] = hostname
#获取ip地址,不确定获取那个
ip = socket.gethostbyname(hostname)
result["ip"] = ip
#mac地址
mac = uuid.UUID(int = uuid.getnode()).hex[-12:].upper()
mac = ":".join([mac[i:i+2] for i in range(0,11,2)])
result["mac"] = mac
#cpu型号
with os.popen("cat /proc/cpuinfo") as f:
for line in f.readlines():
key,value = line.split(":")
key = key.strip()
value = value.strip()
if key == "model name":
cpuData = value
break
result["cpu"] = cpuData
#内存大小
with os.popen("cat /proc/meminfo") as f:
for line in f.readlines():
key,value = line.split(":")
key = key.strip()
value = value.strip()
if key == "MemTotal":
MemTotal = value
break
result["memtotal"] = MemTotal
print(result)
效果如下:
但是我们又会发现这样做还是不够好,我们应该将有参数的放到函数或类当中,那么我们试试用类和装饰器写一写,进行简单的结构编写。
#!/usr/bin/env python3
#coding:utf-8
import os
import uuid
import socket
class GetData(object):
def __init__(self):
self.result = {} #实例化最终的结果
def getData_byFile(self,command,keyword):
“”“
统一的获取文件当中参数的方法
”“”
result = ""
with os.popen(command) as f:
for line in f.readlines():
key,value = line.split(":")
key = key.strip()
value = value.strip()
if key == keyword:
result = value
break
return result
def get_cpu(self):
command = "cat /proc/cpuinfo"
keyword = "model name"
cpuData = self.getData_byFile(command,keyword)
return cpuData
def get_mem(self):
command = "cat /proc/meminfo"
keyword = "MemTotal"
meminfo = self.getData_byFile(command,keyword)
return meminfo
def get_hostname(self):
hostname = socket.gethostname()
return hostname
def get_ip(self):
ip = socket.gethostbyname(hostname)
return ip
def get_mac(self):
mac = uuid.UUID(int = uuid.getnode()).hex[-12:].upper()
mac = ":".join([mac[i:i+2] for i in range(0,11,2)])
result["mac"] = mac
return mac
在上面的基础上我们再进行优化一次
#!/usr/bin/env python3
#coding:utf-8
import os
import uuid
import socket
class GetData(object):
def __init__(self):
self.result = {}
def getData_byFile(self,command,keyword):
result = ""
with os.popen(command) as f:
for line in f.readlines():
key,value = line.split(":")
key = key.strip()
value = value.strip()
if key == keyword:
result = value
break
return result
def get_cpu(self):
command = "cat /proc/cpuinfo"
keyword = "model name"
cpuData = self.getData_byFile(command,keyword)
return cpuData
def get_mem(self):
command = "cat /proc/meminfo"
keyword = "MemTotal"
meminfo = self.getData_byFile(command,keyword)
def get_cpu(self):
command = "cat /proc/cpuinfo"
keyword = "model name"
cpuData = self.getData_byFile(command,keyword)
return cpuData
def get_mem(self):
command = "cat /proc/meminfo"
keyword = "MemTotal"
meminfo = self.getData_byFile(command,keyword)
return meminfo
def get_hostname(self):
self.hostname = socket.gethostname()
return self.hostname
def get_ip(self):
ip = socket.gethostbyname(self.hostname)
return ip
def get_mac(self):
mac = uuid.UUID(int = uuid.getnode()).hex[-12:].upper()
mac = ":".join([mac[i:i+2] for i in range(0,11,2)])
return mac
def getAll(self):
self.result = {
"mac": self.get_mac(),
"hostname": self.get_hostname(),
"ip": self.get_ip(),
"cpuData": self.get_cpu(),
"memtotal": self.get_mem()
}
if __name__ == "__main__":
data = GetData()
data.getAll()
print(data.result)
but,在生成键值对这里我们不必单独进行生成,我们可以写一个装饰器,将其放入我们的字典中。
#!/usr/bin/env python3
#coding:utf-8
import os
import uuid
import socket
class GetData(object):
def __init__(self):
self.result = {}
def getResult(fun):
def inner(self):
key,value = fun(self)
self.result[key] = value #这里需要键值对
return inner
def getData_byFile(self,command,keyword):
result = ""
with os.popen(command) as f:
for line in f.readlines():
key,value = line.split(":")
key = key.strip()
value = value.strip()
if key == keyword:
result = value
break
return result
@getResult
def get_cpu(self):
command = "cat /proc/cpuinfo"
keyword = "model name"
cpuData = self.getData_byFile(command,keyword)
return "cpu",cpuData
@getResult
def get_mem(self):
command = "cat /proc/meminfo"
keyword = "MemTotal"
meminfo = self.getData_byFile(command,keyword)
return "meminfo",meminfo
@getResult
def get_hostname(self):
self.hostname = socket.gethostname()
return "hostname",self.hostname
@getResult
def get_ip(self):
ip = socket.gethostbyname(self.hostname)
return "ip",ip
@getResult
def get_mac(self):
mac = uuid.UUID(int = uuid.getnode()).hex[-12:].upper()
mac = ":".join([mac[i:i+2] for i in range(0,11,2)])
return "mac",mac
def getAll(self):
self.result = {
"mac": self.get_mac(),
"hostname": self.get_hostname(),
"ip": self.get_ip(),
"cpuData": self.get_cpu(),
"memtotal": self.get_mem()
}
if __name__ == "__main__":
data = GetData()
data.get_cpu()
data.get_mem()
data.get_hostname()
print(data.result)
到这里一个比较完整的脚本就完成了,当然也还是有可以优化的地方,值得注意的是我们在查询ip的时候是调用了我们的主机名来进行查询的。所以说一定要有先后顺序进行查询,如果先查询ip就会报错。
查看装饰的步骤
- get_houstname作为参数,传入getResult
- key,value = fun(self)实例化了get_houstname key = hostname value = self.hostname
- 不论装饰器装饰了啥,返回的都是inner函数
- self.method == method(self)
服务器数据采集的发送
我们开始设置我们的接口
\ALLENCMDB\Server\views.py
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
from django.views.generic import View
class Api(View):
def post(self,request):
if request.POST:
postData = request.POST
return HttpResponse(postData)
def get(self,request):
if request.GET:
getData = request.GET["key"]
return HttpResponse(getData)
设置好url,通过浏览器访问没有问题
那么我们通过脚本来测试一下,首先保证你的Linux服务器能够与你的服务器能够互相ping通
WebServer:192.168.1.32
LinuxServer:192.168.1.53
然后在linuxserver上编写脚本,注意,如果Django服务器想被其他人访问自己,那么需要监听所有ip
然后用脚本请求,我们进行请求的代码
#!/usr/bin/env python3
#coding:utf-8
import requests
url = "http://192.168.1.32:8000/Api/"
data = {
"type": "user_login",
"data": {
"username": "root",
"password": "123456"
},
"token": ""
}
response = requests.post(url,data = data)
with open("1.html","w") as f:
f.write(response.content)
print(response)
在接口请求的过程当中,如果发现请求的数据发送不成功,请将嵌套部分进行json封装
请求的代码
#!/usr/bin/env python3
#coding:utf-8
import json
import requests
url = "http://192.168.1.32:8000/Api/"
#对发送数据嵌套部分进行json封装
login_data = json.dumps({
"username": "root",
"password": "123456"
})
data = {
"type": "user_login",
"data": login_data,
"token": ""
}
response = requests.post(url,data = data)
result = response.json()
print(result)
\ALLENCMDB\Server\views.py
import json
from django.views.generic import View
from django.http import JsonResponse,HttpResponse
class Api(View):
def __init__(self,**kwargs):
View.__init__(self,**kwargs)
self.result = {
"status": "",
"data": {}
}
def post(self,request):
"""
处理post请求
"""
if request.POST:
postData = request.POST
post_type = postData.get("type") #获取类型
if post_type == "user_login":
login_data = json.loads(postData.get("data")) #获取登录数据,这里获取的是提交的json字符串
username = login_data.get("username") #获取用户名
self.result["status"] = "success"
self.result["data"]["token"] = "211314"
else:
self.result["status"] = "error"
self.result["data"]["error"] = "no method named %s"%postData
return JsonResponse(self.result)
def get(self, request):
"""
处理get请求
"""
if request.GET:
getData = request.GET.get("key")
return HttpResponse(getData)
我们利用上述脚本请求的时候会报错, 这里我们一定要注意类视图的一些特性。
然后将我们的视图代码修改
from django.views.generic import View
from django.http import JsonResponse,HttpResponse
class Api(View):
"""
"""
def __init__(self,**kwargs):
View.__init__(self,**kwargs)
self.result = {
"status": "",
"data": {}
}
def post(self,request):
"""
处理post请求
"""
if request.POST:
postData = request.POST.get("type")
if postData == "user_login":
self.result["status"] = "success"
self.result["data"]["token"] = "211314"
else:
self.result["status"] = "error"
self.result["data"]["error"] = "no method named %s"%postData
return JsonResponse(self.result)
def get(self, request):
"""
处理get请求
"""
if request.GET:
getData = request.GET.get("key")
return HttpResponse(getData)
完善我们的token机制
上面我们已经疏通了我们接口的基本样式,那么我们现在来完成完整的接口请求流程。
1. 确定我们的登录用户
进行登录逻辑的编写,首先完善登录的基本逻辑
import json
from django.views.generic import View
from django.http import JsonResponse,HttpResponse
from Service.models import LoginUser,Service,APIToken
class API(View):
def __init__(self,**kwargs):
View.__init__(self,**kwargs)
self.result = {
"status": "",
"data": {}
}
def post(self,request):
"""
处理post请求
"""
if request.POST:
postData = request.POST
post_type = postData.get("type") #获取类型
login_data = json.loads(postData.get("data")) # 获取登录数据,这里获取的是提交的json字符串
if post_type == "user_login":
username = login_data.get("username") #获取接口提交的用户名
password = login_data.get("password") #获取接口提交的密码
try:
loginUser = LoginUser.objects.get(username = username)
except:
self.result["status"] = "error"
self.result["data"]["error"] = "no user named %s"%username
else:
db_password = loginUser.password
if password == db_password:
self.result["status"] = "success"
self.result["data"]["token"] = "201314"
else:
self.result["status"] = "success"
self.result["data"]["token"] = "%s's password is wrong"%username
else:
self.result["status"] = "error"
self.result["data"]["error"] = "no method named %s"%postData
return JsonResponse(self.result)
def get(self, request):
"""
处理get请求
"""
if request.GET:
getData = request.GET.get("key")
return HttpResponse(getData)
在我们真正的代码实现过程当中,我们登录成功需要干两件事情
- 生成token
我们采用 用户名+当前时间戳进行hash MD5加密的方法生成token
- 保存token到数据库,然后下发token
class Api(View):
def __init__(self,**kwargs):
pass
def post(self,request):
pass
def get(self,request):
pass
def makeToken(self, username):
"""
我们采用 用户名+当前时间戳进行hash MD5加密的方法生成token:
"""
time_stamp = str(time.time()) # 获取了当前时间的时间戳,并转化为字符串
value = username + time_stamp # 进行用户名和字符串类型的时间戳的拼接
# md5加密,并返回
md5 = hashlib.md5()
md5.update(value.encode())
token = md5.hexdigest()
return token
我们来看一下token的使用,我们借助服务器信息注册来使用一下token
Token使用,我们实际上使用的是一种校验的方法
class Api(View):
def __init__(self,**kwargs):
pass
def post(self,request):
pass
def get(self,request):
pass
def makeToken(self, username):
pass
def tokenValid(self,token):
"""
校验token
"""
try:
db_token = APIToken.objects.get(value = token)
except:
return "token error"
else:
# 从数据库取出的时间转换为时间戳
db_time_tuple = db_token.time.timetuple() #转换时间的格式为元组格式
db_time_stamp = time.mktime(db_time_tuple) #讲元组格式的时间转换为时间戳
# 当前的时间转换为时间戳
now_time_tuple = datetime.datetime.now().timetuple() # 转换时间的格式为元组格式
now_time_stamp = time.mktime(now_time_tuple) # 讲元组格式的时间转换为时间戳
if 0 < now_time_stamp - db_time_stamp < 3600: #秒
return "ok"
else:
db_token.delete()
return "time out"
我们来编写服务器注册的案例
import time
import json
import hashlib
import datetime
from django.views.generic import View
from django.http import JsonResponse,HttpResponse
from Service.models import LoginUser,Service,APIToken
class API(View):
def __init__(self,**kwargs):
View.__init__(self,**kwargs)
self.result = {
"status": "",
"data": {}
}
def post(self,request):
"""
处理post请求
"""
if request.POST:
post_type = request.POST.get("type") #获取类型
postData = json.loads(request.POST.get("data")) # 获取登录数据,这里获取的是提交的json字符串
if post_type == "user_login":
username = postData.get("username") #获取接口提交的用户名
password = postData.get("password") #获取接口提交的密码
try:
loginUser = LoginUser.objects.get(username = username)
except:
self.result["status"] = "error"
self.result["data"]["error"] = "no user named %s"%username
else:
db_password = loginUser.password
if password == db_password:
token = self.makeToken(username) #调用方法生成token
#将token存入数据库
db_token = APIToken() #实例化api token数据模型,传入值
db_token.value = token
db_token.time = datetime.datetime.now()
db_token.user_id = loginUser.id #这里调用上面登录时候的用户id进行token对应
db_token.save()
self.result["status"] = "success"
self.result["data"]["token"] = token
else:
self.result["status"] = "success"
self.result["data"]["token"] = "%s's password is wrong"%username
elif post_type == "addServer":
if postData:
postToken = request.POST.get("token")
if postToken and self.tokenValid(postToken) == "ok":
#获取数据
ip = postData.get("ip")
mac = postData.get("mac")
cpu = postData.get("cpu")
memory = postData.get("memory")
hostname = postData.get("hostname")
#保存数据
server = Service()
server.ip = ip
server.mac = mac
server.cpu = cpu
server.memory = memory
server.hostname = hostname
server.isalive = "false"
server.save()
self.result["status"] = "success"
self.result["data"]["result"] = "save success"
else:
self.result["status"] = "error"
self.result["data"]["error"] = "token error"
else:
self.result["status"] = "error"
self.result["data"]["error"] = "data error"
else:
self.result["status"] = "error"
self.result["data"]["error"] = "no method named %s"%postData
return JsonResponse(self.result)
def get(self, request):
"""
处理get请求
"""
if request.GET:
getData = request.GET.get("key")
return HttpResponse(getData)
def makeToken(self,username):
"""
我们采用 用户名+当前时间戳进行hash MD5加密的方法生成token:
"""
time_stamp = str(time.time()) #获取了当前时间的时间戳,并转化为字符串
value = username + time_stamp #进行用户名和字符串类型的时间戳的拼接
#md5加密,并返回
md5 = hashlib.md5()
md5.update(value.encode())
token = md5.hexdigest()
return token
def tokenValid(self,token):
"""
校验token
"""
try:
db_token = APIToken.objects.get(value = token)
except:
return "token error"
else:
# 从数据库取出的时间转换为时间戳
db_time_tuple = db_token.time.timetuple() #转换时间的格式为元组格式
db_time_stamp = time.mktime(db_time_tuple) #讲元组格式的时间转换为时间戳
# 当前的时间转换为时间戳
now_time_tuple = datetime.datetime.now().timetuple() # 转换时间的格式为元组格式
now_time_stamp = time.mktime(now_time_tuple) # 讲元组格式的时间转换为时间戳
if 0 < now_time_stamp - db_time_stamp < 3600: #秒
return "ok"
else:
db_token.delete()
return "time out"
请求的脚本:
#!/usr/bin/env python3
#coding:utf-8
import json
import requests
url = "http://192.168.1.32:8000/Api/"
#对发送数据嵌套部分进行json封装
server_data = json.dumps({
"ip": "192.169.1.53",
"mac": "00:01:6C:06:A6:29",
"cpu": "Intel(R) Core(TM) i7-3632QM CPU @ 2.20GHz",
"memory": "180000KB",
"hostname": "saltmaster",
})
data = {
"type": "addServer",
"data": server_data,
"token": "a97ff61fddb10e52064563952e511bd7"#这里的token是根据前面的脚本请求得到的token
}
response = requests.post(url,data = data)
result = response.json()
print(result)
实际工作当中,我们请求的代码会写出如下
#!/usr/bin/env python3
#coding:utf-8
import json
import requests
class RequestApi:
def __init__(self,username,password,url):
self.url = url #传入地址
self.request_data = json.dumps({
"username": username,
"password": password
}) #定义了登录的数据
self.requestData = {
"type": "user_login",
"data": self.request_data,
"token": ""
} #定义发送的数据
self.token = self.request("post").get("data").get("token")
def request(self,method):
"""
method是我们用get还是post请求
"""
#发起请求
response = requests.request(method,url = self.url,data = self.requestData)
result = response.json()
return result
def addServer(self):
server_data = json.dumps({
"ip": "192.169.1.5.",
"mac": "00:01:6C:06:A6:29",
"cpu": "Intel(R) Core(TM) i7-3632QM CPU @ 2.20GHz",
"memory": "180000KB",
"hostname": "saltmaster",
})
self.reqeustData["data"] = server_data
self.requestData["type"] = "addServer"
self.requestData["token"] = self.token
self.request("post")
if __name__ == "__main__":
url = "http://192.168.1.32:8000/Api/"
username = "allen"
password = "123"
req = RequestApi(username,password,url)
print(req.token)
效果如下:
当然我们也可以进行批量插入服务器信息,方便后面的Vue分页使用数据:
#!/usr/bin/env python3
#coding:utf-8
import json
import requests
url = "http://192.168.1.32:8000/Api/"
for i in range(1,101):
server_data = json.dumps({
"ip":"192.168.1.%s"%i,
"mac":"00:0C:29:8B:9A:85",
"cpu":"Intel(R) Core(TM) i7-7500 CPU @ 3.40GHz",
"memory":"521314KB",
"disk":"8888MB"
})
data = {
"type":"addServer",
"data":server_data,
"token":"95d1244538e89f5bf91a4e6dd9b6918d"
}
response = requests.post(url,data = data)
result = response.json()
print(result)
效果如下:
上面的信息中在存入数据库时打错了字段名称,所以disk字段没有信息,修改后正常存入信息