UI界面实现SSH登录服务器并执行命令监控
一、通过paramiko实现SSH远程登录服务器、执行命令并返回信息;
二、通过wxpython实现UI化;
三、代码实现如下:
1)主程序MainUI
#coding:utf8 #!/usr/bin/env python #@author: 9527 import wx from MainFrameUI import MainFrameUI#子类化wxpython应用程序 #定义wx.App的子类 class MainApp(wx.App): #@author: 9527 #定义一个应用程序的初始化方法 def OnInit(self): #启动主程序 #创建一个MainFrame的实例 win = MainFrameUI(None) #设置窗口的尺寸800*638 win.SetSize((1100, 800)) #设置窗体放置在屏幕中心 win.CenterOnScreen() #显示或隐藏窗口(Frame框架可见)。其中的参数可以为 True 或False。 #frame.Hide() # 等同于frame.Show(False) win.Show(show = True) #设计为应用程序的顶级窗口,此处即将win设计为顶级窗口 self.SetTopWindow(win) return True if __name__ == "__main__":#创建wx.App子类(MainApp)的实例,实例化 #这行创建了应用程序对象。这行之后,所有发送到stderr或stdout的文本 #都可被wxPython重定向到一个框架。参数redirect=True决定了是否重定向。 #如果值为True,则重定向到框架,如果值为False,则输出到控制台。 app = MainApp() #应用程序进入消息循环 app.MainLoop()
2)UI框架MainFrameUI
#coding:UTF-8 #!/usr/bin/env python #author by No9527 import wx import PicturepackageUI import MultipleEffectiveServerResourceMonitorUI as MESRM from threading import Thread import queue class MainFrameUI(wx.Frame): #@author: 9527 def __init__(self,parent): wx.Frame.__init__(self,parent,-1,title="服务器资源监控",pos=wx.DefaultPosition, style=wx.SIMPLE_BORDER|wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX) self.Ssh_load = None #定义信息列表 self.Info_List = [] self.Info_List2= [] #设置程序最小化图标 self.SetIcon(PicturepackageUI.monitor_png.GetIcon()) #绑定工具按钮与对应事件 self.action_or_stop = True #初始化循环为真 #消息定义队列 self.QueueInfo = queue.Queue(100000) #********************************************************************************* #设置panel面板1 self.panel1 = wx.Panel(self,pos=(-1,40),size=(1100,120)) self.panel1.SetBackgroundColour("#33cccc") #主机IP地址 self.IP_Addr0 = wx.StaticText(self.panel1, label="主机IP地址", pos=(10, 34)) # 单行文本输入框(加了验证器) self.IP_Addr1 = wx.TextCtrl(self.panel1, id=wx.ID_ANY, pos=(75, 30), size=(150, -1)) #用户名 self.UserName0 = wx.StaticText(self.panel1, label="用户名", pos=(240, 34)) self.UserName1 = wx.TextCtrl(self.panel1, id=wx.ID_ANY, pos=(280, 30), size=(150, -1)) #密码 self.password0 = wx.StaticText(self.panel1, label="登录密码", pos=(440, 34)) # 密码输入框 self.password1 = wx.TextCtrl(self.panel1, id=wx.ID_ANY, style=wx.TE_PASSWORD, pos=(490, 30), size=(150, -1)) #命令 self.command0 = wx.StaticText(self.panel1, label="sar命令", pos=(650, 34)) # 密码输入框 self.command1 = wx.TextCtrl(self.panel1,value="sar -n DEV 5 -u -r", id=wx.ID_ANY, pos=(695, 30), size=(150, -1)) #确定按钮 self.ok_btn = wx.Button(self.panel1, -1, "添加", pos=(75,80),size=(70, 20)) #取消按钮 self.cancel_btn = wx.Button(self.panel1, -1, "清空", pos=(165,80),size=(70, 20)) #********************************************************************************* #设置panel面板2 self.panel2 = wx.Panel(self,pos=(-1,150),size=(1100,200)) self.panel2.SetBackgroundColour("#ff9966") CommandInfo0=["sar命令用法: sar [ 选项 ] [ <时间间隔> [ <次数> ] ]", "主选项和报告:", "-b I/O 和传输速率信息状况", "-B 分页状况", "-d 块设备状况", "-I { <中断> | SUM | ALL | XALL } 中断信息状况", "-m 电源管理信息状况", "-n { <关键词> [,...] | ALL } 网络统计信息", "关键词可以是:", "DEV 网卡信息统计", "EDEV 网卡的错误统计", "NFS NFS客户端", "NFSD NFS服务器", "SOCK Sockets (IPV4套接字)", "IP IP流(IPV4)", "EIP IP流的错误统计(IPV4)", "ICMP ICMP流(IPV4)", "EICMP ICMP流的错误统计(IPV4)", "TCP TCP流(IPV4)", "ETCP TCP流的错误统计(IPV4)", "UDP UDP流(IPV4)", "SOCK6 Sockets(IPV6套接字)", "IP6 IP流(IPV6)", "EIP6 IP流的错误统计(IPV6)", "ICMP6 ICMP流(IPV6)", "EICMP6 ICMP流的错误统计 (IPV6)", "UDP6 UDP流(IPV6) ", "-q 队列长度和平均负载", "-r 内存利用率", "-R 内存状况", "-S 交换空间利用率", "-u [ ALL ]", "CPU 利用率", "-v Kernel table 状况", "-w 任务创建与系统转换统计信息", "-W 交换信息", "-y TTY 设备状况", "-o {<文件路径>}"] #加入换行符链接 CommandInfo1 = "\n".join(CommandInfo0) #设置命令提示文本框 self.CommandInfoTip = wx.StaticText(self.panel2, label="sar监测命令帮助", pos=(565, 15),size = (480,50), style = wx.ALIGN_CENTRE_HORIZONTAL) self.CommandInfoTip.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.NORMAL)) self.CommandInfo = wx.TextCtrl(self.panel2,value=CommandInfo1,pos=(565, 45),size = (490,150), style = wx.TE_READONLY|wx.TE_MULTILINE) # 用户名与密码显示区,内容通过后续在OnButtonClick中调用SetLabel实现 self.up_monitor = wx.StaticText(self.panel2, label="当前登录信息", pos=(30, 15),size = (480,50), style = wx.ALIGN_CENTRE_HORIZONTAL) self.up_monitor.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.NORMAL)) self.up_monitor = wx.TextCtrl(self.panel2,value="登录信息显示在这里",pos=(30, 45),size = (490,150), style = wx.TE_READONLY|wx.TE_MULTILINE) # 控件与事件绑定在一起 self.Bind(wx.EVT_BUTTON, self.OnButtonClick, self.ok_btn) self.Bind(wx.EVT_BUTTON, self.OnButtonClick, self.cancel_btn) #********************************************************************************** #设置panel面板3 self.panel3 = wx.Panel(self,pos=(-1,350),size=(1100,450)) self.panel3.SetBackgroundColour("#00cc99") # 设置log信息显示面板 self.log_info0 = wx.StaticText(self.panel3, label="log信息显示区", pos=(30, 15),size = (480,50), style = wx.ALIGN_CENTRE_HORIZONTAL) self.log_info0.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.NORMAL)) self.log_info1= wx.TextCtrl(self.panel3,value="log信息显示在这里",pos=(30, 45),size = (1020,300), style = wx.TE_READONLY|wx.TE_MULTILINE) #启用线程间信息传递及文本框显示线程 msd = Thread(target=self.LogInfodisplay) msd.setDaemon(1) msd.start() #********************************************************************************** #设置状态栏及图标工具栏 statusBar = self.CreateStatusBar()#创建状态栏,放置在框架的底部 toolbar = self.CreateToolBar()#创建工具栏,被自动放置在框架的顶部 self.Action = toolbar.AddSimpleTool(wx.NewId(),PicturepackageUI.find_png.getBitmap(), "开始监控","点击开始服务器监控")#给工具栏增加一个工具 self.Stop=toolbar.AddSimpleTool(wx.NewId(),PicturepackageUI.Lock_png.getBitmap(), "停止监控","停止当前监控任务")#给工具栏增加一个工具 #绑定HD图标为开始按钮 self.Bind(wx.EVT_TOOL,self.ActionMonitor,self.Action) #绑定o图标为停止按钮 self.Bind(wx.EVT_TOOL, self.ChangeLoopParameter,self.Stop) toolbar.Realize()#实现显示工具栏 #************************************************************************************** #函数集中定义区 #************************************************************************************** #定义开始按钮事件,开始监控线程 def ActionMonitor(self,event): #@author: 9527 self.action_or_stop = True event.Skip() td = Thread(target=self.ServerMonitor) td.setDaemon(1) td.start() #点击按钮获取输入值 def OnButtonClick(self, event): #@author: 9527 Display_List=[] if event.GetEventObject() == self.ok_btn: print("确定") if self.IP_Addr1.GetValue() == '': wx.MessageBox("主机IP为空,请输入用户名,再继续......", "提示") elif self.UserName1.GetValue() == '': wx.MessageBox("用户名为空,请输入用户名,再继续......", "提示") elif self.password1.GetValue() == '': wx.MessageBox("密码为空,请输入密码,再继续......", "提示") elif self.command1.GetValue() == '': wx.MessageBox("密码为空,请输入密码,再继续......", "提示") else: if self.Info_List == [] : #写入列表 self.Info_List.append(self.IP_Addr1.GetValue()) self.Info_List.append(self.UserName1.GetValue()) self.Info_List.append(self.password1.GetValue()) self.Info_List.append(self.command1.GetValue()) self.Info_List2.append(self.Info_List) self.Info_List = [] else: #清空列表 self.Info_List.clear() for A1 in self.Info_List2 : B1 = ['','',''] B1[0] = '主机IP:' + A1[0] B1[1] = '用户名:' + A1[1] + ' ' B1[2] = '命令:' + A1[3] + ' ' Display_List.append("\n".join(B1)) #显示到面板panel2的“当前登录信息” self.up_monitor.SetLabel("\n".join(Display_List)) if event.GetEventObject() == self.cancel_btn: self.Info_List=[] self.Info_List2.clear() print("清空") if self.IP_Addr1.GetValue() == '': wx.MessageBox("IP地址,请输入用户名,再继续......", "提示") elif self.UserName1.GetValue() == '': wx.MessageBox("用户名为空,请输入密码,再继续......", "提示") elif self.password1.GetValue() == '': wx.MessageBox("密码为空,请输入密码,再继续......", "提示") else: self.IP_Addr1.SetValue("") self.UserName1.SetValue("") self.password1.SetValue("") self.up_monitor.SetLabel("") def ServerMonitor(self): #@author: 9527 Load_list1 = self.Info_List2 #实例化Remote_management_WayKind类 self.Ssh_load = MESRM.Remote_management_WayKind() if self.action_or_stop == True: for Load_list in Load_list1: td = Thread(target=self.Use_Monitor, args=(self, Load_list)) td.setDaemon(1) td.start() else: self.log_info1.AppendText('连接失败请重试\n') pass def Use_Monitor(self, parent, Load_list): #@author: 9527 #调用MESRM.Remote_management_WayKind的Command_Way方法 #传参parent为self是启用进程的MainFrameUI本身,Load_List为登陆了认证信息 print("调用进程已启用: ", Load_list) self.Ssh_load.Command_Way(parent,Load_list) def ChangeLoopParameter(self,event): #@author: 9527 event.Skip() td = Thread(target=self.LoopControl) td.setDaemon(1) td.start() def LoopControl(self): #@author: 9527 if self.action_or_stop == True: self.action_or_stop=False else : self.action_or_stop=True def LogInfodisplay(self): #@author: 9527 while True : AnswerInfo = self.QueueInfo.get() #调用UI的文本控件log_info1添加文本AppendText() self.log_info1.AppendText(AnswerInfo) #计算文本控件行数 Text_counter = self.log_info1.GetNumberOfLines() #判断行数长度,移除前1000字符串 if Text_counter > 200: self.log_info1.Remove(0,1000)
3)SSH登录执行部分MultipleEffectiveServerResourceMonitorUI
#-*- coding: utf-8 -*- #!/usr/bin/python #@author: 9527 ''' 用法: sar [ 选项 ] [ <时间间隔> [ <次数> ] ] 主选项和报告: -b I/O 和传输速率信息状况 -B 分页状况 -d 块设备状况 -I { <中断> | SUM | ALL | XALL } 中断信息状况 -m 电源管理信息状况 -n { <关键词> [,...] | ALL } 网络统计信息 关键词可以是: DEV 网卡信息统计 EDEV 网卡的错误统计 NFS NFS客户端 NFSD NFS服务器 SOCK Sockets (IPV4套接字) IP IP流(IPV4) EIP IP流的错误统计(IPV4) ICMP ICMP流(IPV4) EICMP ICMP流的错误统计(IPV4) TCP TCP流(IPV4) ETCP TCP流的错误统计(IPV4) UDP UDP流(IPV4) SOCK6 Sockets(IPV6套接字) IP6 IP流(IPV6) EIP6 IP流的错误统计(IPV6) ICMP6 ICMP流(IPV6) EICMP6 ICMP流的错误统计 (IPV6) UDP6 UDP流(IPV6) -q 队列长度和平均负载 -r 内存利用率 -R 内存状况 -S 交换空间利用率 -u [ ALL ] CPU 利用率 -v Kernel table 状况 -w 任务创建与系统转换统计信息 -W 交换信息 -y TTY 设备状况 -o {<文件路径>} 将命令结果以二进制格式存放在指定文件中 ''' import paramiko class Remote_management_WayKind(): #@author: 9527 def __init__(self): self def Command_Way(self, parent,Load_list): #@author: 9527 host_addr = Load_list[0] user_name = Load_list[1] ssh_loadkey = Load_list[2] execmd01 = Load_list[3] #创建SSH连接日志文件 paramiko.util.log_to_file("paramiko666.log") # 创建SSH对象 ssh_load = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh_load.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh_load.connect(hostname=host_addr, port=22, username=user_name, password=ssh_loadkey) # 执行命令 stdin, stdout, stderr = ssh_load.exec_command (execmd01, bufsize=1) #execmd传的参数free也是命令 stderr.channel.set_combine_stderr(stdout) #打开屏幕打印log文件,如果没有便新创建,模式a+为追加模式 log_file = open(host_addr+".log", "a+") while parent.action_or_stop: #读取正常返回信息 back_normal_info = stdout.readline() if len(back_normal_info) == 0: break back_normal_info = host_addr + str("设备信息----- \n") +back_normal_info print(back_normal_info) #向队列压入数据,队列在MainFrame中定义 parent.QueueInfo.put(back_normal_info) #写入信息 log_file.writelines(back_normal_info) if parent.action_or_stop == 0: #调用UI的文本控件log_info1添加文本AppendText() parent.QueueInfo.put("********************"+ host_addr + "**********已暂停监控**************\n") #关闭屏幕打印log文件 log_file.close() # 关闭连接 ssh_load.close()
4)图标定义部分PicturepackageUI
#coding:utf8 from wx.lib.embeddedimage import PyEmbeddedImage monitor_png = PyEmbeddedImage("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") find_png = PyEmbeddedImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGhElEQVRIS5VWXVMb1xl+ztmzu1otQuIbJLAdhw9DCIE0GCdOG2rHjj8maT5I3ZnEHeeqV8lM/kBy04v2om5meuGL1J120s542jgXncZp3NqexmZwbWyKMSZ1nAQVJBBIgNAH0u6ec3qxQggRu81z9ep5n/c8Ovu+e85Cfht8enF4bn6hnH0gGL4NLo3caKyrbmyoK0/cH//bQNoWj0V4JCyWFkQkbF05n4vdpQ1B1ryD+mtASHnBZjzIQCzH89cv50eH+cI8hAAg4op9cy5z5yoIiOZRWzv0vfvVjkeJqpcXr+ObDaRj5z77a+7SJyK5Up5zISHzOWty3JqaUB9u9z7/I7ajvVwDACBSyjJKppPpM+9bE2NwU4RQX6US2s6aQlcso9NAVSrOozN8PiItyy0hHo/58nF9YHDrEys3EKvLqV+fdKa/dH8qwWZj31Gtq4+Yvk3F3OEL0dzIpfzVf8hcDgAUxXt0yNj/QpnHJgNpW6nTJ+07twCAUuP7h4zDQ0TzFAXlkJJHw+nfn3IiMwAIY+brP9Ef31sq2WSw9unZ7LmPICUUxXzluOfpg8WUBGwus45UKAxGWcm/lNl06vQv7S+mANAKX+Xb7yp1wWJ2w4DHIslfvCNzayDEeO5F75FXC7zE1ynn+qIVzXJHSgAmIx1+tb9WC+jU1chMKvneuzw2D0B/fKDix2+CFlLrUyRl7vJ5mVsDwLY9ZDz7gkvnuTwfyU2u2KKkU6u2vB637qzYB0OezoAKgJg+89U3Vk/9HFxYk/9yItOsZacrLhiITMqauAEAhHiPDBFNB8Alzs2sTSUdVwMAUhZ7mHHkX2ZyCiHtfgZAbevWuvus8Rsyn7fGrpYb8GhYrCwDUJpCrLXLJSeX7c/XV7ey6cit0ZW5GVU3Gtofqd3ZQSi1hbwwl2s2TS8jIEQfGLRu3YSU9ucTOOKAsQ0DZ/qeO/VqaydRNQBc4kbcch+MlUmP/uk3q7EoAELIEw3einRlvDIEYDkv7ibt3hoNANv+MDUrRDrFY1GRSVF/1YYBX4i6AQu2uEHGFrEcd+MvRy66qwNQmXL8+QPhucWzsaivPgjgq5TjGlDDpFU1Ip2Sti1WFgsGFy//Mzw754yHxbIC4LBRtQ0AkHak21gp+NJ/vnJXB2DZzps/fW8tnw/uedY1WLWlBAggqTIM/8yyAoD9+RKtvXPwmT3MV2HWVgcsD+NMAlBRGJeSQSdkfeZcRBcTAEJbTgUAPiKqmASg+01aHVBVlfX3dQNIJ6byyWkAZmbJlVaoRCHgEoTSup0dxUfkgml6VctDbhzQaMFK8B6R7PIJAP7BPWxbK4o9UBqa3YDPht1ZNBkNepWZDAewY/f3kvOziel77lvJNL1j8JBZU++WtFYWFpGZFF9KACC6TqtqXbKQU3e0ghBIaX8xKe080TyUoL9Wi2TXhITqMXpffH3x3tTK3Iyqe+pbOysbQm5hvYe2rRs4X9+V2QwApTFEvT6XXN9BU4tSW8cXF3h8wZ4c0/qeBNDuV/uq+c2EJQGm6U1dvU1dva7ehcHIgZBHVwgACJEbuejyWlcvFMWNCwbEa2qP9a/9/WNIZD85q+7qIYZJCfYHdY3iWtzimw51AAho9GiLZ3tFYQVr4rr970kAxDC0voGirHijEc/TB/JXPxPpFJ+PZj/+o/nKCRDCKBkMelr96njCms3yHJcU8Gu0rZI9VqOZ64eqWFrInP0AQgLQe3cXO4oSA9DqeuPwS5kPP4CUuSsXiFnhPTQEQgjQYirNpsEFbCEpgUrJ+twAgFhJpN4/KVaWANBAlXF4qPTO2XyjcSf9h1P50REAIETvf8r7g9eoL7AhKIMU9t3bmTOneWIRANF13xtvqV19pZLyK1OuZVK/+1XhUgNoVbVn7z79ie/SQDVooW8ApJV3wvdyl8/bt8ek4wAgTDWPndAHBje9o1sNAMh8LvPRb/PXhsELZxFRmRLapjSGLuTNHkPUZhJ8NswT8WIJrQyYx05oj+4uMkV8gwEACG6NX8ue+5DH5krpn8WUl/2i3VNSwpje8x3j6A+VuqYNsgQbTd4Eqmh9T6q7eqyxkfzosBOdlWvZwlcMAIAwRir9aluX56l9bHtb8YLcivvsoBTcEcllHo+J5cV3zvztWP+u7s5WWtOg1DYQw9z6IVSG++ygFAqj1XW0ug4AvXCb9ezWuneVa+6P/8OgBC8990wo2FjOPhD/BbW2KHA+cIJSAAAAAElFTkSuQmCC") Lock_png = PyEmbeddedImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADSUlEQVRIS7WWP4zcRBSHf288Y693vbfH5cIhRAKIKETJNSESokU0ICQEBVAgpQEakFIhSkQNHU2a1EFCSgIVCBBCgeZoDqQgQQDlhDZEl4S77F/bY48fxS4be2xv9iD5Oj979vN789ZviJlxL5EAmFnrOMvupklKqZTCRGBMqrW2H/l/GJPeFhSLxAADImMIysenMOwFeYjsNdK6FtfPU9Tdvv+tL26op1awvs8nojAcT+6mJrt6Y2CyrLhoChHWVoKmp/JBW0DJDiV/xyYdGTVKIYQgIiKa9EKWcWpMVpsBGWO7iZmTJImicBowIViz7PQTBBJSEIB8pyVpltVmQEo5kxoRURC0Uc4Ajg/4BHQUUPzpCUoKQFjBOdgCIlHapz3AzNY72QLf9x3HsYKLE8eR1fG24K6zqCBJ0+5f29du7nhKHnzwgdWV5XLLV7KQ4Odf/zj98YXLW91YayFEu9V8+snjb7z6Qjto2Y+WsNu02WxZe7Cxeem9j86EsQYgiPjf1lo/9MgH774dFB2zPahv0yI7u70Pz5wNY70ctE6++OyJ9SOD0ejTry5+s7F56fet02cvvPPma/NrdQfBl99tXN+91fDc90+9/sT6kUnw2OFDneCTc19f/PaHzZMvPbe2f19xUYE7CH785TcAJ44ePn7s8VnQccQrzz/z+fcbw3F4pXvtvwuYeRxGAA6s7bfq0A5avuuOo7jX6+fjZeYJFsH+kpSYJxgmLBvNVnspk95uXPjAjTU3WkGLSUPqjN3K0QFgTptuDdLP/gyHYZQZI5VSys0vY3Achszsut5DS+7LjzYnjj206eV+OkqZlOcoMKBLE1t4PgADXB2ZvubVRnUStYL6qVIB1+9FraDMINLd3tCTzsP3LTn1RbfYg+DmKNQm0yYbat1pePbtGmzBbByWZ5nvqn6cCCKvNDCMyYwBqgprC2btlKbFG0Cn4W4Pxp50PFVYxUAchePqOV0SzCHNmIDKM4v92jkkgLlfw9v4ynlstUPAYo9PkQCkVJ5nD2tHpIDJR6QQ0q04TxDgKtd1C97ZUJmWyHULf1QAB9rip1vhnNxntJRYbnqerE5semQrw4wrg7SXVFQ8DwEHA7niVWQ24R9+NXciwcXtRQAAAABJRU5ErkJggg==")

浙公网安备 33010602011771号