python 开发的 windows版运维图形界面-信息管理系统
基于运维人员对windows/linux/网络设备系统管理比较分散,并且每个服务都要开启不同的监控和应用程序,浪费时间,浪费时间就是浪费金钱的道理没有人不会不懂这个道理,我查找了很多资源发现都是一些零散的监控工具,没有正真意思的统一监控管理(博主时间有限。目前只分享windows本地监控,后面继续更新远程监控),并且运维人员查看网络或者虚拟机信息都要远程登录,而本工具可以在本地直接写命令,获取远程配置信息,极大的提高运维人员的工作效率和节约成本时间。 1.登陆首页展示和代码分享 #登陆页面 deflog_in(self): """ 登录界面 :return: """ try: logging.info('***StsrtIMS***') var1=StringVar()#id框中的文字 var2=StringVar()#密码框中的文字 self.root.geometry('450x380'+self.winfo_landing_x+self.winfo_landing_y)#设置主界面大小 self.root.resizable(0,0)#禁止调整窗口大小 self.root.title("信息化管理系统") #登录主界面分成两行一列 logging.info('Startloadingbackgroundimage') #================背景图================== #组件.grid(row=x,column=y)将组件放入self.root中(x,y)位置 f=Frame(width=523,height=150,bg='green')#frame1 canvas=tk.Canvas(self.root,width=525,height=150,bg='yellow')#canvas1 self.img=itk.PhotoImage(file="img/win.png") canvas.create_image(209,75,image=self.img) canvas.grid(row=0,column=0,columnspan=2,padx=1,pady=3) #======================================= logging.info('Endloadingbackgroundimage') logging.info('Startloadingthegraybox') #================下灰框================== f=Frame(width=520,height=220,bg='#DCDCDC')#frame2 f_head=Frame(width=80,height=80,bg='green')#frame3 #======================================= logging.info('Endloadingthegraybox') logging.info('Startloadingavatar') #=================头像=================== self.canvas2=tk.Canvas(self.root,width=80,height=80,bg='red') self.img2=Img.open("img/TX.png") self.img2=itk.PhotoImage(self.img2) self.canvas2.create_image(40,40,image=self.img2) self.canvas2.place(in_=f_head,anchor=NW)#canvas2放入frame3中,位置是偏西北 f_head.place(relx=0.10,rely=0.56)#frame3放入root的绝对位置上 #======================================= logging.info('Endloadingavatar') logging.info('Startloadinguseraccounts') #===============用户账号==================Entry1直接放入self.root的绝对位置上,也可以尝试放入frame2中 self.usr=Entry(self.root,textvariable=var1,bg='#F5F5F5',highlightcolor='#1E90FF') self.usr.place(relx=0.35,rely=0.56) #======================================= logging.info('Endloadinguseraccounts') logging.info('Startloadingthepasswordbox') #===============密码框====================Entry2直接放入self.root的绝对位置上 self.pwd=Entry(self.root,textvariable=var2,bg='#F5F5F5',highlightcolor='#1E90FF') self.pwd['show']='*' self.pwd.place(relx=0.35,rely=0.65) #======================================= logging.info('Endloadingthepasswordbox') logging.info('Startloadingautomaticlogin') #自动登录 #checkbutton放入绝对位置 rem_pwd=Checkbutton(self.root,foreground='#1E90FF').place(relx=0.34,rely=0.72)#选择框 #设置颜色,字体,宽,长compound=LEFT,foreground='#808080',bg='#DCDCDC' rem_pwd_lab=Label(self.root,width=6,height=1,text='自动登录', foreground='#808080') rem_pwd_lab.place(relx=0.39,rely=0.72) #======================================= logging.info('Endloadingautomaticlogin') logging.info('Startloadingtherememberpassword') #==============记住密码=================== rem_pwd=Checkbutton(self.root,foreground='#1E90FF').place(relx=0.51,rely=0.72)#选择框 rem_pwd_lab=Label(self.root,width=6,height=1,text='记住密码', foreground='#808080')#设置颜色,字体,宽,长compound=LEFT,foreground='#808080',bg='#DCDCDC' rem_pwd_lab.place(relx=0.56,rely=0.72)#设计找回密码字体大小 #======================================= logging.info('Endloadingtherememberpassword') #=============登录按钮==================== login_btn=Button(self.root,text='登陆',bg='#1E90FF')#按钮,字体颜色,按钮背景色:bg='#1E90FF' login_btn.place(relx=0.36,rely=0.8)#设置登录坐标位置X,Y login_btn.bind("<Button-1>",self.load)#触发函数执行 #======================================= #===============注册用户================== fgt_usr_btn=Button(self.root,text='注册账号',foreground='#1E90FF',command=self.regiser)#灰色:bg='#DCDCDC' fgt_usr_btn.place(relx=0.7,rely=0.54) #fgt_usr_btn.bind("<Button-1>",self.regiser) #======================================= #===============找回密码================= fgt_pwd_btn=Button(self.root,text='找回密码',foreground='#1E90FF',command=self.fg_pwd)#灰色:bg='#DCDCDC' fgt_pwd_btn.place(relx=0.7,rely=0.64) #fgt_pwd_btn.bind("<Button-1>",self.fg_pwd)#模拟enter按钮 #fgt_pwd_btn.flash() #======================================= exceptExceptionasloginerror: logging.info(str(loginerror)) print(str(loginerror)) #登陆认证 defload(self,*args): """ 登录事件 :paramargs: :return: """ try: logging.info('Startrunningtheloginevent') user=self.usr.get() pwd=self.pwd.get() License_p=time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())) hl=hashlib.md5() hl.update(pwd.encode(encoding='utf8')) pwd_md5_jm=hl.hexdigest() print('加密前为:'+pwd) print('加密后为:'+hl.hexdigest()) ifLicense_p<=self.LICENSE_TIMES: withopen(r'db\imsap.txt','r',encoding='utf8')asf: foriinf: user1=i.strip().split(':')[2] pwd2=i.strip().split(':')[3] ifuser==user1andpwd2==pwd_md5_jm: #ifself.username==userandself.password==pwd_md5_jm: logging.info('loginsuccessful') print('登录成功') self.root.quit()#关闭登录窗口 self.root.destroy()#destroy()销毁一个小部件,quit()退出mainloop。 print('已关闭登陆界面。。') print('开始加载主页面。。') logging.info('Startloadingpage') #self.cs1() t1=threading.Thread(target=self.cs1()) t1.start() t1.join() logging.info('Endloadingpage') print('主页面加载结束。。') else: print('登录失败') lbtime2=tk.Label(self.root,fg='red',anchor='w') lbtime2.place(x=156,y=180,width=150) lbtime2['text']='请输入正确的用户名或密码' #messagebox.showinfo(title='登陆日志',message='用户名或密码错误,请重新登录') else: lbtime2=tk.Label(self.root,fg='red',anchor='w') lbtime2.place(x=149,y=180,width=155) lbtime2['text']='License已过期,请联系管理员授权!' logging.info('Endrunningtheloginevent') exceptExceptionasruuingerror: print(str(ruuingerror)) #账号注册页面 defregiser(self,*args): """ 登录账号注册 :paramevent: :return: """ self.ycsy=tk.Tk() self.ycsy.title('登录账号注册')#设置窗口标题 self.ycsy.geometry("580x265+460+300")#设置窗口大小宽,高 self.ycsy.resizable(width=False,height=False)#宽不可变,高可变,默认为True name=tk.StringVar() ttk.Label(self.ycsy,text="").grid(row=0,column=1,columnspan=1) tk.Label(self.ycsy,text="用户ID*",font=("黑体",10,"bold"),width=40,height=3,wraplength=80,anchor='w').grid( row=1,column=1,columnspan=1) tk.Label(self.ycsy,text="用户名*",font=("黑体",10,"bold"),width=40,height=3,wraplength=80,anchor='w').grid( row=1,column=2,columnspan=1) self.name_id=tk.StringVar() self.name_id_sr=ttk.Entry(self.ycsy,width=20,textvariable=self.name_id) self.name_id_sr.grid(row=1,column=1) self.name_id_sr.focus() self.name_zc=tk.StringVar() self.name_zc_sr=ttk.Entry(self.ycsy,width=20,textvariable=self.name_zc) self.name_zc_sr.grid(row=1,column=2) self.name_zc_sr.focus() tk.Label(self.ycsy,text=u"账号状态",font=("黑体",10,"bold"),width=40,height=3,wraplength=80,anchor='w').grid( row=2,column=1) tk.Label(self.ycsy,text=u"密码*",font=("黑体",10,"bold"),width=40,height=3,wraplength=80,anchor='w').grid( row=2,column=2) self.account_zc=tk.StringVar() self.account_zc_sr=ttk.Combobox(self.ycsy,width=18,textvariable=self.account_zc, state='readonly')#下拉框字体,内容为weather,宽度,state='editable'表示内容可编辑 self.account_zc_sr['values']=('可用','禁用')#设置下拉列表的值 self.account_zc_sr.grid(column=1,row=2)#设置其在界面中出现的位置column代表列row代表行 self.account_zc_sr.current(0) self.pwd_zc=tk.StringVar() self.pwd_zc_sr=ttk.Entry(self.ycsy,width=20,textvariable=self.pwd_zc,show='*') self.pwd_zc_sr.grid(row=2,column=2) self.pwd_zc_sr.focus() tk.Label(self.ycsy,text=u"邮箱*", font=("黑体",10,"bold"), width=40,height=3,wraplength=80,anchor='w').grid(row=3,column=1) tk.Label(self.ycsy,text=u"确认密码*",font=("黑体",10,"bold"), width=40,height=3,wraplength=80, anchor='w').grid(row=3,column=2) self.email_zc=tk.StringVar() self.email_zc_sr=ttk.Entry(self.ycsy,width=20,textvariable=self.email_zc) self.email_zc_sr.grid(row=3,column=1) self.email_zc_sr.focus() self.pwd_qr_zc=tk.StringVar() self.pwd_qr_zc_sr=ttk.Entry(self.ycsy,width=20,textvariable=self.pwd_qr_zc,show='*') self.pwd_qr_zc_sr.grid(row=3,column=2) self.pwd_qr_zc_sr.focus() tk.Label(self.ycsy,text=u"手机号码*", font=("黑体",10,"bold"), width=40,height=3,wraplength=80, anchor='w').grid(row=4,column=1) tk.Label(self.ycsy,text=u"信息安全", font=("黑体",10,"bold"), width=40,height=3,wraplength=80,anchor='w').grid(row=4,column=2) self.phone_zc=tk.StringVar() self.phone_zc_sr=ttk.Entry(self.ycsy,width=20,textvariable=self.phone_zc) self.phone_zc_sr.grid(row=4,column=1) self.phone_zc_sr.focus() self.ifm_zc=tk.StringVar() self.ifm_zc_sr=ttk.Combobox(self.ycsy,width=18,textvariable=self.ifm_zc,state='readonly') self.ifm_zc_sr['values']=('不加密','加密')#设置下拉列表的值 self.ifm_zc_sr.grid(column=2,row=4)#设置其在界面中出现的位置column代表列row代表行 self.ifm_zc_sr.current(0) #=============注册确定按钮==================== #button3放入绝对位置 login_btn=Button(self.ycsy,text='确定',bg='#1E90FF',command=self.regiser_file) login_btn.place(relx=0.38,rely=0.8) #login_btn.bind("<Button-1>",'执行函数') #======================================= #=============注册取消按钮====================button3放入绝对位置 login_btn=Button(self.ycsy,text='关闭',bg='#1E90FF',command=self.regiser_cancel) login_btn.place(relx=0.49,rely=0.8) #login_btn.bind("<Button-1>",self.regiser_cancel) #======================================= #账号注册确定 defregiser_file(self,*args): """ 注册确定事件 :return: """ self.id_file_p=self.name_id_sr.get()#用户ID self.name_file_p=self.name_zc_sr.get()#用户名 self.accout_file_p=self.account_zc_sr.get()#账号状态 self.pwd_file_p=self.pwd_zc_sr.get()#密码 #密码加密----------------------------------- hl=hashlib.md5() hl.update(self.pwd_file_p.encode(encoding='utf8')) self.pwd_file_p=hl.hexdigest() #密码加密----------------------------------- self.email_file_p=self.email_zc_sr.get()#邮箱 self.pwd_qr_file_p=self.pwd_qr_zc_sr.get()#确认密码 self.phone_file_p=self.phone_zc_sr.get()#手机号码 self.ifm_file_p=self.ifm_zc_sr.get()#信息安全 ifself.name_file_porself.pwd_file_porself.pwd_qr_file_p!=''andself.pwd_file_p!=self.pwd_qr_file_p: #[IMSAP]:用户ID:用户名,密码,邮箱,手机号码,账号状态,信息安全 file_imsap='[IMSAP]:{0}:{1}:{2}:{3}:{4}:{5}:{6}'.format( self.id_file_p, self.name_file_p, self.pwd_file_p, self.email_file_p, self.phone_file_p, self.accout_file_p, self.ifm_file_p, self.ifm_file_p ).replace('','') withopen(r'report\imsap.txt','a',encoding='utf8')asf: f.writelines(file_imsap+'\n') f.close() lbtime2=tk.Label(self.ycsy,fg='red',anchor='w') lbtime2.place(x=205,y=2,width=160) lbtime2['text']='提示:已注册成功请登录' else: lbtime2=tk.Label(self.ycsy,fg='red',anchor='w') lbtime2.place(x=210,y=2,width=160) lbtime2['text']='提示:带“*”为必填项!!' ##密码 ifself.pwd_file_p!=self.pwd_qr_file_p: lbtime2=tk.Label(self.ycsy,fg='red',anchor='w') lbtime2.place(x=205,y=2,width=160) lbtime2['text']='提示:密码不一致!!' #账号注册取消 defregiser_cancel(self): """ 注册取消事件 :return: """ self.ycsy.destroy() #找回密码 deffg_pwd(self,*args): """ 找回密码事件 :paramevent: :return: """ messagebox.showinfo(title='找回密码',message='程序正在更新中......') 1.1 代码执行效果图 2.代码监控部分逻辑代码 deffbytes(B): 'ReturnthegivenbytesasahumanfriendlyKB,MB,GB,orTBstring' B=float(B) KB=float(1024) MB=float(KB**2)#1,048,576 GB=float(KB**3)#1,073,741,824 TB=float(KB**4)#1,099,511,627,776 ifB<KB: return'{0}{1}'.format(B,'Bytes'if0==B>1else'Byte') elifKB<=B<MB: return'{0:.2f}KB'.format(B/KB) elifMB<=B<GB: return'{0:.2f}MB'.format(B/MB) elifGB<=B<TB: return'{0:.2f}GB'.format(B/GB) elifTB<=B: return'{0:.2f}TB'.format(B/TB) classHandler(http.server.BaseHTTPRequestHandler): """SimpleHTTPrequesthandlerwithGET/HEAD/POSTcommands. Thisservesfilesfromthecurrentdirectoryandanyofits subdirectories.TheMIMEtypeforfilesisdeterminedby callingthe.guess_type()method.Andcanreveivefileuploaded byclient. TheGET/HEAD/POSTrequestsareidenticalexceptthattheHEAD requestomitstheactualcontentsofthefile. """ defdo_GET(self): """ServeaGETrequest.""" f=self.send_head() iff: self.copyfile(f,self.wfile) f.close() defdo_HEAD(self): """ServeaHEADrequest.""" f=self.send_head() iff: f.close() defdo_POST(self): """ServeaPOSTrequest.""" r,info=self.deal_post_data() print((r,info,"by:",self.client_address)) f=BytesIO() f.write(b'<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML3.2Final//EN">') f.write(b"<html>\n<title>UploadResultPage</title>\n") f.write(b'<styletype="text/css">\n') f.write(b'*{font-family:Helvetica;font-size:16px;}\n') f.write(b'a{text-decoration:none;}\n') f.write(b'</style>\n') f.write(b"<body>\n<h2>UploadResultPage</h2>\n") f.write(b"<hr>\n") ifr: f.write(b"<strong>Success!</strong>") else: f.write(b"<strong>Failed!</strong>") f.write(info.encode()) f.write(("<br><br><ahref=\"%s\">"%self.headers['referer']).encode()) f.write(b"<button>Back</button></a>\n") f.write(b"<hr><small>PoweredBy:bones7456<br>Checknewversion") f.write(b"<ahref=\"https://gist.github.com/UniIsland/3346170\"target=\"_blank\">") f.write(b"here</a>.</small></body>\n</html>\n") length=f.tell() f.seek(0) self.send_response(200) self.send_header("Content-type","text/html") self.send_header("Content-Length",str(length)) self.end_headers() iff: self.copyfile(f,self.wfile) f.close() defdeal_post_data(self): uploaded_files=[] content_type=self.headers['content-type'] ifnotcontent_type: return(False,"Content-Typeheaderdoesn'tcontainboundary") boundary=content_type.split("=")[1].encode() remainbytes=int(self.headers['content-length']) line=self.rfile.readline() remainbytes-=len(line) ifnotboundaryinline: return(False,"ContentNOTbeginwithboundary") whileremainbytes>0: line=self.rfile.readline() remainbytes-=len(line) fn=re.findall(r'Content-Disposition.*name="file";filename="(.*)"',line.decode()) ifnotfn: return(False,"Can'tfindoutfilename...") path=self.translate_path(self.path) fn=os.path.join(path,fn[0]) line=self.rfile.readline() remainbytes-=len(line) line=self.rfile.readline() remainbytes-=len(line) try: out=open(fn,'wb') exceptIOError: return(False,"<br><br>Can'tcreatefiletowrite.<br>Doyouhavepermissiontowrite?") else: without: preline=self.rfile.readline() remainbytes-=len(preline) whileremainbytes>0: line=self.rfile.readline() remainbytes-=len(line) ifboundaryinline: preline=preline[0:-1] ifpreline.endswith(b'\r'): preline=preline[0:-1] out.write(preline) uploaded_files.append(fn) break else: out.write(preline) preline=line return(True,"<br><br>'%s'"%"'<br>'".join(uploaded_files)) defsend_head(self): """CommoncodeforGETandHEADcommands. ThissendstheresponsecodeandMIMEheaders. Returnvalueiseitherafileobject(whichhastobecopied totheoutputfilebythecallerunlessthecommandwasHEAD, andmustbeclosedbythecallerunderallcircumstances),or None,inwhichcasethecallerhasnothingfurthertodo. """ path=self.translate_path(self.path) f=None ifos.path.isdir(path): ifnotself.path.endswith('/'): #redirectbrowser-doingbasicallywhatapachedoes self.send_response(301) self.send_header("Location",self.path+"/") self.end_headers() returnNone forindexin"index.html","index.htm": index=os.path.join(path,index) ifos.path.exists(index): path=index break else: returnself.list_directory(path) ctype=self.guess_type(path) try: #Alwaysreadinbinarymode.Openingfilesintextmodemaycause #newlinetranslations,makingtheactualsizeofthecontent #transmitted*less*thanthecontent-length! f=open(path,'rb') exceptIOError: self.send_error(404,"Filenotfound") returnNone self.send_response(200) self.send_header("Content-type",ctype) fs=os.fstat(f.fileno()) self.send_header("Content-Length",str(fs[6])) self.send_header("Last-Modified",self.date_time_string(fs.st_mtime)) self.end_headers() returnf deflist_directory(self,path): """Helpertoproduceadirectorylisting(absentindex.html). Returnvalueiseitherafileobject,orNone(indicatingan error).Ineithercase,theheadersaresent,makingthe interfacethesameasforsend_head(). """ try: list=os.listdir(path) exceptos.error: self.send_error(404,"Nopermissiontolistdirectory") returnNone enc=sys.getfilesystemencoding() list.sort(key=lambdaa:a.lower()) f=BytesIO() displaypath=html.escape(urllib.parse.unquote(self.path)) f.write(b'<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML3.2Final//EN">') f.write(b'<html>\n') f.write(('<metahttp-equiv="Content-Type"' 'content="text/html;charset=%s">'%enc).encode(enc)) f.write(("<title>Directorylistingfor%s</title>\n"%displaypath).encode(enc)) f.write(b'<styletype="text/css">\n') f.write(b'*{font-family:Helvetica;font-size:16px;}\n') f.write(b'a{text-decoration:none;}\n') f.write(b'a:link{text-decoration:none;font-weight:bold;color:#0000ff;}\n') f.write(b'a:visited{text-decoration:none;font-weight:bold;color:#0000ff;}\n') f.write(b'a:active{text-decoration:none;font-weight:bold;color:#0000ff;}\n') f.write(b'a:hover{text-decoration:none;font-weight:bold;color:#ff0000;}\n') f.write(b'table{\nborder-collapse:separate;\n}\n') classVrvAgent(): """主逻辑""" def__init__(self): self.app=wx.App()#创建应用程序对象 self.win=wx.Frame(None,-1, title='设备配置管理系统', size=(710,620), pos=(500,100), style=wx.SYSTEM_MENU|wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX)#创建窗体 self.taskBarIcon=TaskBarIcon(frame=self.win) self.agent_menu()#菜单栏 self.agent_box()#页面 defagent_menu(self): """ 总菜单栏 :return: """ self.memBar=wx.MenuBar()#初始化菜单栏 self.agent_fileMenu_f()#文件 self.agent_deitMenu_e()#编辑 self.agent_helpMenu_h()#帮助 self.win.SetMenuBar(self.memBar)#启动菜单栏 defagent_fileMenu_f(self): """ 菜单栏-文件 :return: """ #------------------------------文件 file_menu=wx.Menu()#二级 newItem=wx.MenuItem(file_menu,id=wx.ID_NEW,text="新建(N)\tCtrl+N",kind=wx.ITEM_NORMAL) openItem=wx.MenuItem(file_menu,id=wx.ID_OPEN,text="打开(O)...\tCtrl+O",kind=wx.ITEM_NORMAL) saveItem=wx.MenuItem(file_menu,id=wx.ID_SAVE,text="保存(S)\tCtrl+S",kind=wx.ITEM_NORMAL) #saveItem.SetBitmap(wx.Bitmap("exit.png"))#添加保存图标 saveasItem=wx.MenuItem(file_menu,id=wx.ID_SAVEAS,text="另存为(A)...",kind=wx.ITEM_NORMAL) exitItem=wx.MenuItem(file_menu,id=20,text="退出(X)",kind=wx.ITEM_NORMAL) file_menu.Append(newItem)#newItem此属性添加带菜单栏 file_menu.Append(openItem) file_menu.Append(saveItem) file_menu.Append(saveasItem) file_menu.AppendSeparator()#选项之间添加一行线 file_menu.Append(exitItem) self.win.Bind(wx.EVT_MENU,self.OnExit,saveasItem)#执行另存为函数 self.win.Bind(wx.EVT_MENU,self.OnExit,exitItem)#执行退出函数 self.memBar.Append(file_menu,title="文件(F)")#一级 #------------------------------文件 defagent_deitMenu_e(self): """ 菜单栏-编辑 :return: """ deitMenu=wx.Menu() ftpclient=wx.MenuItem(id=21,text="FTP客户端\tCtrl+W",kind=wx.ITEM_NORMAL) ftpserver=wx.MenuItem(id=21,text="FTP服务端\tCtrl+Q",kind=wx.ITEM_NORMAL) #deitMenu.Append(id=21,item="FTP服务端\tCtrl+Q",kind=wx.ITEM_NORMAL) self.memBar.Append(deitMenu,title="工具(E)") deitMenu.Append(ftpclient) deitMenu.Append(ftpserver) self.win.Bind(wx.EVT_MENU,self.ftpclient,ftpclient)#执行退出函数 self.win.Bind(wx.EVT_MENU,self.ftpserver,ftpserver)#执行退出函数 defftpclient(self,event): """ ftp客户端 """ print('ccc') defftpserver(self,event): """ ftp服务端 """ FTP_files().ftp_files() defagent_helpMenu_h(self): """ 菜单栏-帮助 :return: """ helpMenu=wx.Menu() editMenu=wx.Menu()#初始化三级 cutItem=wx.MenuItem(editMenu,id=122,text="Cut",kind=wx.ITEM_NORMAL)#三级 editMenu.Append(cutItem)#添加三级 helpMenu.Append(wx.ID_ANY,"Edit",editMenu)#二级 self.memBar.Append(helpMenu,title="帮助(H)")#一级 2.1代码结果图示列