1.效果图
2.客户端(tkinter) myClient.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# Python2.x 导入方法
# from Tkinter import * # 导入 Tkinter 库
# Python3.x 导入方法
from tkinter import *
import tkinter.simpledialog
from tkinter import ttk
# import mysocket
import mySockectClient as mysocket
import time
import threading
import os
class MainWindow():
def __init__(self):
self.root = Tk() # 创建窗口对象的背景色
self.root.title("客户端")
self.root.geometry('1060x680')
self.root.minsize(1060, 680) # 最小尺寸
self.root.maxsize(1060, 680) # 最大尺寸
self.setup_UI()
self.load_data()
def setup_UI(self):
# 标题
self.title=Label(self.root, text='主机列表')
#连接状态
self.state = StringVar()
self.state.set('未连接')
self.label = Label(self.root, textvariable=self.state,fg="red",font=('隶书',14))
#IP
self.listb = Listbox(self.root)
#内存使用情况
self.treeRam=ttk.Treeview(self.root,show="headings",columns=("men/swap","total","used","free","shared","buff/cache","available"))
self.treeRam.column("men/swap",anchor="center",width=100) #表示列
self.treeRam.column("total",anchor="center",width=100)
self.treeRam.column("used",anchor="center",width=100)
self.treeRam.column("free",anchor="center",width=100)
self.treeRam.column("shared",anchor="center",width=100)
self.treeRam.column("buff/cache",anchor="center",width=100)
self.treeRam.column("available",anchor="center",width=100)
self.treeRam.heading("men/swap",text="") #显示表头
self.treeRam.heading("total",text="总内存")
self.treeRam.heading("used",text="已使用")
self.treeRam.heading("free",text="未使用")
self.treeRam.heading("shared",text="共享内存")
self.treeRam.heading("buff/cache",text="缓存/缓冲区")
self.treeRam.heading("available",text="新进程可用")
#日志
self.listb2 = Listbox(self.root,selectmode=SINGLE)
#主要数据表格
self.tree=ttk.Treeview(self.root,show="headings",columns=("id","data"))
self.tree.column("id",width=40) #表示列
self.tree.column("data",width=660)
self.tree.heading("id",text="编号") #显示表头
self.tree.heading("data",text="值")
#按钮
self.b1 = Button(self.root,text='连 接',command=self.connectbutton)
self.b2 = Button(self.root,text='添 加',command=self.askip)
self.b3 = Button(self.root,text='删 除',command=self.delip)
# self.b3 = Button(self.root,text='删 除',command=lambda x=self.listb:x.delete(ACTIVE))
self.b4 = Button(self.root,text='清 空 日 志',command=self.dellog,font=('隶书',10))
self.b5 = Button(self.root,text='查 看 进 程',state=DISABLED,command=self.send)
self.b6 = Button(self.root,text='动 态 显 示',state=DISABLED,command=self.send2)
self.b7 = Button(self.root,text='暂 停 进 程',state=DISABLED,command=self.stop)
self.b8 = Button(self.root,text='恢 复 进 程',state=DISABLED,command=self.cont)
self.b9 = Button(self.root,text='终 止 进 程',state=DISABLED,command=self.kill)
self.b10 = Button(self.root,text='开启自动处理报警',state=DISABLED,command=self.autoKillStateFunc)
self.b11 = Button(self.root,text='设置报警值',state=DISABLED,command=self.setCpuRam)
# 创建自动报警处理类型
# self.autoType = tkinter.Label(self.root,text='请选择您的自动报警处理类型:',fg='blue')
# 创建单选项
self.autoType = tkinter.IntVar()
self.male_select = tkinter.Radiobutton(self.root,text='暂停',state=DISABLED,value=1,variable=self.autoType,command=self.func)
self.female_select = tkinter.Radiobutton(self.root,text='终止',state=DISABLED,value=2,variable=self.autoType,command=self.func)
self.cpuValue = StringVar() #CPU报警值
self.cpuValue.set("cpu报警值")
self.e1 = Entry(self.root, textvariable=self.cpuValue,state=DISABLED)
self.ramValue = StringVar() #内存报警值
self.ramValue.set("ram报警值")
self.e2 = Entry(self.root, textvariable=self.ramValue,state=DISABLED)
# 将小部件放置到主窗口中(定位)
self.title.place(x=50,y=20, anchor=CENTER)
self.label.place(x=130,y=20, anchor=CENTER)
self.b1.place(x=90,y=50, anchor=CENTER)
self.b2.place(x=90,y=80, anchor=CENTER)
self.b3.place(x=90,y=110, anchor=CENTER)
self.b4.place(x=840,y=660, anchor=CENTER)
self.b5.place(x=970,y=40, anchor=CENTER)
self.b6.place(x=970,y=70, anchor=CENTER)
self.b7.place(x=970,y=100, anchor=CENTER)
self.b8.place(x=970,y=130, anchor=CENTER)
self.b9.place(x=970,y=160, anchor=CENTER)
self.b10.place(x=970,y=190, anchor=CENTER)
self.b11.place(x=970,y=310, anchor=CENTER)
# self.autoType.place(x=970,y=220, anchor=CENTER)
self.male_select.place(x=940,y=220, anchor=CENTER)
self.female_select.place(x=1000,y=220, anchor=CENTER)
self.listb.place(x=90,y=390, anchor=CENTER)
self.treeRam.place(x=530,y=500, anchor=CENTER)
self.listb2.place(x=530,y=600, anchor=CENTER)
self.tree.place(x=530,y=240, anchor=CENTER)
self.e1.place(x=970,y=250, anchor=CENTER)
self.e2.place(x=970,y=280, anchor=CENTER)
#样式
self.b1.config(width=20)
self.b2.config(width=20)
self.b3.config(width=20)
self.b5.config(width=20)
self.b6.config(width=20)
self.b7.config(width=20)
self.b8.config(width=20)
self.b9.config(width=20)
self.b10.config(width=20)
self.b11.config(width=20)
# b4.config(height=1)
self.listb.config(height=28)
self.treeRam.config(height=3)
self.listb2.config(height=5,width=100)
self.tree.config(height=20)
#初始数据
def load_data(self):
#ip数据
self.ip= ['116.62.45.23','109.228.65.219','135.52.0.224 ','31.230.45.33 ','106.65.141.9 ','145.21.29.204 ','193.75.134.28 ']
self.ram=[]
#日志数据
self.log = []
#控制台数据
self.records=[]
#当前ip
self.currentip=''
#轮询的线程
self.c = None #线程类
self.t = None #创建线程对象
self.rt=None
self.rtt=None
self.folder() #创建文件夹
self.readip() #读取文件的ip地址
self.readlog() #读取日志文件
#报警自动终止进程:开启、关闭
self.autoKill=True
#自动处理数据的结果
self.autoData=None
# #CPU报警值
# self.cpuValue=10
# #内存报警值
# self.ramValue=10
#IP
for item in self.ip:
self.listb.insert(0,item)
#内存使用情况
for item in list(self.ram):
i+=1
self.tree.insert("","end",values=(i,item))
#日志
for item in self.log:
self.listb2.insert(0,item)
#主要数据
for item in list(self.records):
i+=1
self.tree.insert("","end",values=(i,item))
# 新增IP并写入文件
def askip(self):
# 获取字符串(标题,提示,初始值)
result = tkinter.simpledialog.askstring(title = '添加IP',prompt='请输入IP:',initialvalue = '127.0.0.1')
if(result!=None and result!=""):
# 打印内容
# print(result)
self.listb.insert(0,result)
self.ip.append(result)
self.writeip() #写入IP
self.addlog('添加IP '+result)
#删除IP并写入文件
def delip(self):
ipindex=self.listb.curselection()
if(ipindex!=()):
ipindex=self.listb.curselection()[0] #选中下标的数据
ip=self.listb.get(ipindex)
self.listb.delete(ipindex)
self.ip.reverse() #倒叙
self.ip.pop(ipindex) #删除
self.ip.reverse() #再倒叙回来
self.writeip() #写入IP
self.addlog('删除IP: '+ip)
#添加日志
def addlog(self,handle):
curtime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
self.log.append(curtime+' '+handle+' '+self.currentip)
# self.log.reverse()
self.listb2.insert(0,curtime+' '+handle+' '+self.currentip)
# self.log.reverse()
self.writelog()
#清空日志并写入文件
def dellog(self):
self.listb2.delete(0,"end")
self.log=[]
self.writelog()
# 连接服务器
def connectbutton(self):
#返回元组:如果为空则没选择,否则返回选择的元组下标
if(self.listb.curselection()==()):
tkinter.messagebox.showinfo('提示','没有选择ip地址')
else:
index=self.listb.curselection()[0] #获取选择的下标
ip=self.listb.get(index)
try:
result=mysocket.send(ip,'0')
li=result[0].split(' ')
#返回的设备状态
self.autoKill=li[0]
self.autoType.set(li[1])
self.cpuValue.set(li[2])
self.ramValue.set(li[3])
if(li[0]=="True"):
self.b10['text']="关闭自动处理报警"
self.male_select.config(state=DISABLED)
self.female_select.config(state=DISABLED)
self.autoKill=False
else:
self.b10['text']="开启自动处理报警"
self.male_select.config(state=NORMAL)
self.female_select.config(state=NORMAL)
self.autoKill=True
#判断是否连接成功
self.state.set('已连接')
self.label.config(fg="green")
self.currentip=ip # 赋值给当前IP
tkinter.messagebox.showinfo('状态','连接成功')
self.b5.config(state=NORMAL)
self.b6.config(state=NORMAL)
self.b7.config(state=NORMAL)
self.b8.config(state=NORMAL)
self.b9.config(state=NORMAL)
self.b10.config(state=NORMAL)
self.b11.config(state=NORMAL)
self.e1.config(state=NORMAL)
self.e2.config(state=NORMAL)
#开启内存轮询,清除数据列表
if(self.rtt==None):
self.rt=RamThread()
self.rtt = threading.Thread(target=self.rt.run, args=(0,self,)) #创建线程对象
self.rtt.start()
else:
print("关闭线程")
self.b6['text']='动 态 显 示'
if(self.c!=None):self.c.terminate() #关闭线程
# self.t.join() #已经关闭子线程,不用等待子线程结束
self.t=None #清空线程
self.c=None
except Exception as x:
self.state.set('未连接')
self.label.config(fg="red")
self.currentip='' # 赋值给当前IP
tkinter.messagebox.showerror('连接失败',x)
self.cpuValue.set('cpu报警值')
self.ramValue.set('ram报警值')
self.b5.config(state=DISABLED)
self.b6.config(state=DISABLED)
self.b7.config(state=DISABLED)
self.b8.config(state=DISABLED)
self.b9.config(state=DISABLED)
self.b10.config(state=DISABLED)
self.b11.config(state=DISABLED)
self.e1.config(state=DISABLED)
self.e2.config(state=DISABLED)
self.male_select.config(state=DISABLED)
self.female_select.config(state=DISABLED)
self.currentip=''
#关闭线程轮询
self.b6['text']='动 态 显 示'
if(self.c!=None):self.c.terminate() #关闭线程
# self.t.join() #已经关闭子线程,不用等待子线程结束
self.t=None #清空线程
self.c=None
#关闭内存轮询
if(self.rtt!=None):
if(self.rt!=None):self.rt.terminate() #关闭线程
# self.t.join() #已经关闭子线程,不用等待子线程结束
self.rtt=None #清空线程
self.rt=None
#判断是否已连接
def onLine(self):
if(self.currentip==""):
tkinter.messagebox.showinfo('提示','未连接')
return False
else:
return True
# 查询内存轮询
def ramMethod(self):
li=[]
if(self.onLine()):
#清除数据列表
x=self.treeRam.get_children()
for item in x:
self.treeRam.delete(item)
try:
#发送请求
result=mysocket.send(self.currentip,"2")
self.ram=result
# print(result)
#拆解字符串
for item in list(self.ram):
for item2 in item.split(" "):
if(item2!=''):
li.append(item2.replace('\\','').replace("'",'').replace(",",'').replace("]",'')) #添加并去掉反斜杠
self.treeRam.insert("","end",values=(li[8],li[9],li[10],li[11],li[12],li[13],li[14]))
self.treeRam.insert("","end",values=(li[16],li[17],li[18],li[19],'',''))
#判断是否有报警信息
if(li[21]!=""):
self.addlog(li[21]+' '+li[22]+' '+li[23]+' '+li[24]+' '+li[25])#添加到日志
except Exception as x:
tkinter.messagebox.showerror('连接失败',x)
# 查询数据
def send(self):
if(self.onLine()):
#清除数据列表
x=self.tree.get_children()
for item in x:
self.tree.delete(item)
try:
#发送请求
result=mysocket.send(self.currentip,"1")
for i in range(len(result)):
# if('报警' not in result[i]):
item=result[i].replace("', '",'')
self.tree.insert("","end",values=(i,item))
# elif('报警' in result[i]):
# self.addlog(result[i].replace("', '",'').replace("']",''))
except Exception as x:
tkinter.messagebox.showerror('连接失败',x)
#线程轮询查询,可关闭
def send2(self):
if(self.onLine()):
#判断线程是否为空,(空则创建,有则关闭)
if(self.t==None):
print("开启线程")
self.b6['text']='关 闭 动 态'
self.c=DownThread()
self.t = threading.Thread(target=self.c.run, args=(0,self,)) #创建线程对象
self.t.start()
else:
print("关闭线程")
self.b6['text']='动 态 显 示'
if(self.c!=None):self.c.terminate() #关闭线程
# self.t.join() #已经关闭子线程,不用等待子线程结束
self.t=None #清空线程
self.c=None
#终止进程
def kill(self):
pid = tkinter.simpledialog.askstring(title = 'PID',prompt='请输入PID:',initialvalue = '1')
if(pid!=None and pid!=''):
mysocket.send(self.currentip,"3/"+pid)
tkinter.messagebox.showinfo('提示','已完成')
self.addlog('终止进程:'+pid)
#暂停进程
def stop(self):
pid = tkinter.simpledialog.askstring(title = 'PID',prompt='请输入PID:',initialvalue = '1')
if(pid!=None and pid!=''):
mysocket.send(self.currentip,"4/"+pid)
tkinter.messagebox.showinfo('提示','已完成')
self.addlog('暂停进程:'+pid)
#恢复进程
def cont(self):
pid = tkinter.simpledialog.askstring(title = 'PID',prompt='请输入PID:',initialvalue = '1')
if(pid!=None and pid!=''):
mysocket.send(self.currentip,"5/"+pid)
tkinter.messagebox.showinfo('提示','已完成')
self.addlog('恢复进程:'+pid)
#切换报警自动处理
def autoKillStateFunc(self):
if(self.autoKill):
self.b10['text']="关闭自动处理报警"
self.male_select.config(state=DISABLED)
self.female_select.config(state=DISABLED)
self.autoKill=False
else:
self.b10['text']="开启自动处理报警"
self.male_select.config(state=NORMAL)
self.female_select.config(state=NORMAL)
self.autoKill=True
result=mysocket.send(self.currentip,"autoSwitch/"+str(self.autoKill)+"/"+str(self.autoType.get()))
tkinter.messagebox.showinfo('提示',result[0])
self.addlog('报警自动处理 '+result[0])
def func(self):
print(self.autoType.get())
#设置报警值
def setCpuRam(self):
result=mysocket.send(self.currentip,"6/"+self.cpuValue.get()+"/"+self.ramValue.get())
tkinter.messagebox.showinfo('提示',result[0])
self.addlog('设置报警值 '+result[0])
#创建空文件夹
def folder(self):
folder="appman"
if(os.path.exists(folder)!=True):
os.mkdir(folder)
#读取ip文件
def readip(self):
doc_path="appman/ip.txt"
if(os.path.exists(doc_path)!=True): #不存在则创建
open(doc_path,"w")
with open(doc_path, "r") as f: # 打开文件
data = f.readlines() # 读取文件
self.ip=data
#写入ip文件
def writeip(self):
doc_path="appman/ip.txt"
with open(doc_path,"w+") as f:
#=清除原本数据
f.seek(0)
f.truncate()
for item in self.ip:
if('\n' not in item): #如果没有换行则添加换行
f.write(item+'\n')
else:
f.write(item)
# #读取日志文件
def readlog(self):
doc_path="appman/log.txt"
if(os.path.exists(doc_path)!=True): #不存在则创建
open(doc_path,"w")
with open(doc_path, "r") as f: # 打开文件
data = f.readlines() # 读取文件
self.log=data
#写入日志文件
def writelog(self):
doc_path="appman/log.txt"
with open(doc_path,"w+") as f:
#=清除原本数据
f.seek(0)
f.truncate()
for item in self.log:
if('\n' not in item): #如果没有换行则添加换行
f.write(item+'\n')
else:
f.write(item)
#线程类
class DownThread:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self,n,this_window):
while(self._running):
# print('T-minus', n)
# n += 1
this_window.send()
time.sleep(5)
#内存轮询线程
class RamThread:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self,n,this_window):
while(self._running):
this_window.ramMethod()
time.sleep(10) #十秒一次
if __name__ == '__main__':
#主入口
this_window = MainWindow()
this_window.root.mainloop() # 进入消息循环
print("结束")
3.客户端(socket) mySockectClient.py
# 客户端程序
import socket
import pickle
import threading
import json
#返回的结果
response=''
#判断是否连接成功
def connect(host):
t=threading.Thread(target=threadingconnect(host))
t.start()#开启子线程
t.join()#等待线程
return response
# #判断是否连接成功
# def connect2(host):
# client = socket.socket()
# port=12345
# client.connect((host, port))
# client.send(bytes(json.dumps("0").encode('utf-8')))
# response = client.recv(1)
# client.close()
# return response
def threadingconnect(host):
host=host.replace('\n','').replace(' ','')
port=12345
global response
client = socket.socket()
client.settimeout(3)
client.connect((host, port))
client.send(bytes(json.dumps("0").encode('utf-8')))
response = client.recv(1)
client.close()
response=response
#端口,请求的消息
def send(host,request):
host=host.replace('\n','').replace(' ','')
port=12345
client = socket.socket()
#1.创建和服务器的连接
# host = socket.gethostname()
# host = '116.62.45.23'
client.settimeout(3)
client.connect((host, port))
client.send(request.encode()) #发送请求
msg=bytes()#接收字节对象
fi='jieshu'#结束标志
while(1):
data = client.recv(1024) #接收结果(一次就能接收1024,数值太大接收不完整,所以循环接收多次),
msg += data
if(fi in msg.decode()):
# print(True)#找到结束标识跳出循环
break
client.close()
# msg=str(msg)
msg=msg.decode()
msg=msg.replace('jieshu', '').replace('b\'["', '').replace('", "', '') #格式化结果集
msg=''.join(msg).split('\\n')
# print(msg) #根据换行标识截取列表
return msg
# if __name__ == '__main__':
# try:
# print(send('116.62.45.23',"2/"))
# except Exception as x:
# print(x)
4.Linux服务端 server.py
import subprocess
# 服务端程序
import socket
import pickle
import os
import json
import subprocess
import re
import time
import threading
class MyServer():
def __init__(self):
#报警处理进程:开启、关闭
self.autoSwitch=False
#报警处理类型(1暂停、2终止)
self.autoType='1'
#自动处理数据的结果
self.autoData=None
#CPU报警值
self.cpuValue=10
#内存报警值
self.ramValue=10
#开启自动报警线程
p = threading.Thread(target=self.alarm_module)
p.start()
#报警模块:自动发送数据
def alarm_module(self):
while(1):
# global autoData
tmp = os.popen("ps -aux").readlines()
tmp.pop(0) #删除第一行
for i in range(len(tmp)):
#print(tmp[i])
try:
l=re.sub(' +', ' ', tmp[i]) #多个空格变一个空格
except:
continue
# print(l)
li=l.split(' ') #根据空格隔开数据
# print(li[1]+" "+li[2]+" "+li[3]+" "+li[10]+" ")
# break
if(float(self.cpuValue)<=float(li[2])):
print("CPU报警 PID:"+li[1]+" 名称:"+li[10].replace('\n','')+' CPU占比值:'+li[2])
self.autoData="CPU报警 PID:"+li[1]+" 名称:"+li[10].replace('\n','')+' CPU占比值:'+li[2]
if(self.autoSwitch and self.autoType=="1"):
tmp = os.popen("kill -STOP "+li[1]).readlines()
self.autoData+=" 已自动暂停进程PID:"+li[1]
print("自动暂停进程PID:"+li[1])
elif(self.autoSwitch and self.autoType=="2"):
tmp = os.popen("kill "+li[1]).readlines()
self.autoData+=" 已自动终止进程PID:"+li[1]
elif(float(self.ramValue)<=float(li[3])):
print("内存报警 PID:"+li[1]+" 名称:"+li[10].replace('\n','')+' 内存占比值:'+li[3])
self.autoData="内存报警 PID:"+li[1]+" 名称:"+li[10].replace('\n','')+' 内存占比值:'+li[3]
if(self.autoSwitch and self.autoType=="1"):
tmp = os.popen("kill -STOP "+li[1]).readlines()
self.autoData+=" 已自动暂停进程PID:"+li[1]
print("自动暂停进程PID:"+li[1])
elif(self.autoSwitch and self.autoType=="2"):
tmp = os.popen("kill "+li[1]).readlines()
self.autoData+=" 已自动终止进程PID:"+li[1]
time.sleep(10) #10秒一次
#服务
def service(self,request):
print("请求:",request)
request=request.replace('"','')
request=request.split('/')
msg="None"
if(request[0]=='0'):
msg=str(self.autoSwitch)+" "+self.autoType+" "+str(self.cpuValue)+" "+str(self.ramValue)
elif(request[0]=='1'):
msg = os.popen("ps -aux").readlines()
elif(request[0]=='2'):
msg = os.popen("free -m").readlines()
#查看报警模块是否有数据,有添加报警数据
if(self.autoData!=None):
msg.append(self.autoData)
self.autoData=None
elif(request[0]=='3'):
msg = os.popen("kill "+request[1]).readlines() #kill进程无返回值
elif(request[0]=='4'):
msg = os.popen("kill -STOP "+request[1]).readlines() #暂停进程
elif(request[0]=='5'):
msg = os.popen("kill -CONT "+request[1]).readlines() #恢复进程
elif(request[0]=='6'): #改变cpu和内存的报警值
self.cpuValue=request[1]
self.ramValue=request[2]
msg="设置完成"
elif(request[0]=='autoSwitch'):
#修改报警自动终止进程状态
if(request[1]=='False'):
self.autoSwitch=True
msg="已开启"
else:
self.autoSwitch=False
msg="已关闭"
self.autoType=request[2]
if(self.autoType=="1"):
msg+=' 自动暂停进程'
else:
msg+=' 自动终止进程'
return msg
def socket(self):
# 1.创建socket(套接字)对象
serv = socket.socket()
# 2.绑定地址信息
host = socket.gethostname()
port = 12345
serv.bind((host, port))
# 3.开启监听
serv.listen(5) # 最大的等待序列数,可以等待5个,第6个就被拒绝了,一般默认是5
print("监听已开启,等待连接。。。。")
# 4.等待从客户端的连接
while 1:
try:
conn, address = serv.accept() # 返回socket连接对象和客户端地址address,是个元组结构
print("连接地址:%s"%(str(address[0])))
request = conn.recvfrom(1024)
response=self.service(request[0].decode()) #根据请求返回结果
if isinstance(response,list):
response.append("jieshu")#发送结束的标志,接受流根据此信息判断是否接受完成
elif isinstance(response,str):
response+="jieshu"#发送结束的标志,接受流根据此信息判断是否接受完成
conn.send(str(response).encode())
# conn.send(msg.encode('utf-8'))
except Exception as e:
print("异常:",e)
serv.close()
if __name__ == '__main__':
MyServer().socket()