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("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")

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==")

 

posted @ 2022-08-17 13:38  No九五二七9527  阅读(973)  评论(0)    收藏  举报