服務器數據採集與接收
採集數據可以有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.2.215: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.2.215: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字段沒有信息,修改後正常存入信息