開發動機:python
做爲一名專業的運維人員,面對業務系統更新是再正常不過得了,可是面對每週兩次以上,而且都要在晚上才能夠作到的更新,做爲一名有遠大理想並時刻想變技術方面的「糕富帥」的男人,怎麼能夠容忍這樣的單一重複毫無技術含量的工做佔用我過多的時間,一直秉承機器的事情讓機器去處理的原則,說白了就是秉承偷懶的基礎想法,我仍是決定搞個小工具來幫助我處理這樣些煩人的東西。
mysql
開發語言:git
毫無疑問的用了python,別問我爲何。
sql
開發時間:shell
斷斷續續3-4周,其中還要兼顧其餘的工做,若是專心寫估計就2周左右。
編程
開發框架:api
C/S模式,tkinter+fabric+paramiko++mysql+shell,如今不少都用B/S模式,事實上這樣直接操做服務器東西,我的以爲直接放網上的話實在是不安全。安全
開發IDE:服務器
開發內容與過程:
其實這裏我想寫編程思想,語言是思想的承載,沒有思想管你什麼語言你都作不了什麼事情。
一、tkhinter作界面
二、fabric解決透過堡壘機的狀況
三、paramiko解決上傳問題
四、各類內部服務器處理shell
五、mysql裏面導入了當前的服務器的用戶與密碼
六、作好ssh-key信任關係,當前升級機器要在堡壘機跟目標服務器都添加ssh私匙,不作就沒法經過
no code no bb,貼上代碼:
updategui.py
__author__ = 'samfeng' #coding=utf-8 import tkFileDialog, tkMessageBox, os, uploadfile from fabric.api import local from Tkinter import Label, Entry, Button, Text, Tk, END, INSERT, W, E root = Tk() root.title("-----------交易系統業務更新程序-----------") root.geometry('750x680') class Dilog_window_init(): def __init__(self, *args, **kwargs): self.label_blank = Label(root, text='') self.label_step1 = Label(root, text='Step 1:') self.label_step2 = Label(root, text='Step 2:') self.label_step3 = Label(root, text='Step 3:') self.label_step4 = Label(root, text='update file:') self.label_baoleiji = Label(root, text='堡壘機(hostname/ip):') self.label_targethost = Label(root, text='目標主機(hostname/ip):') self.lock_lable = Label(root, width=20) self.hostname_or_ip1 = Entry(root, width=60) self.hostname_or_ip2 = Entry(root, width=60) self.select_file = Entry(root, width=60) self.select_command_file = Entry(root, width=60) self.select_overload_file = Entry(root, width=60) self.select_overload_remote_file = Entry(root, width=60) self.label_upload = Label(root, text='上傳文件:') self.label_command_lujin = Label(root, text='選擇執行腳本路徑:') self.label_overload_lujin = Label(root, text='選擇本地要更新的文件:') self.label_overload__remote_lujin = Label(root, text='填充遠端更新文件路徑:') self.label_overload = Label(root, text='選擇執行腳本路徑:') self.lock1 = Button(root, text='鎖定', command=lambda: self.check_button(1, self.hostname_or_ip1), bg='red', fg='white') self.unlock1 = Button(root, text='不鎖定', command=lambda: self.check_button(0, self.hostname_or_ip1), bg='red', fg='white') self.select_button = Button(root, text='選擇文件', command=lambda: self.selectfile(self.select_file), bg='red', fg='white') self.select_button1 = Button(root, text='選擇文件', command=lambda: self.selectfile(self.select_command_file), bg='red', fg='white') self.select_button2 = Button(root, text='選擇文件', command=lambda: self.selec_update_file(self.select_overload_file), bg='red', fg='white') self.upload_button = Button(root, text='==上 傳==', command=self.upload_to_server, bg='red', fg='white') self.cancel_button = Button(root, text='==取 消==', command=self.cancel_file, bg='red', fg='white') self.lock2 = Button(root, text='鎖定', command=lambda: self.check_button(1, self.hostname_or_ip2), bg='red', fg='white') self.unlock2 = Button(root, text='不鎖定', command=lambda: self.check_button(0, self.hostname_or_ip2), bg='red', fg='white') self.start_button = Button(root, text='===啓動業務===', command=self.start_host, bg='red', fg='white') self.stop_button = Button(root, text='===中止業務===', command=self.stop_host, bg='red', fg='white') self.update_button = Button(root, text='===更新文件===', command=self.update_file, bg='red', fg='white') self.restart_button = Button(root, text='===重啓業務===', command=self.restart_host, bg='red', fg='white') self.help_button = Button(root, text='使用前說明,請點我', command=self.help_t, bg='red', fg='white') self.help_text = Text(root, bg="Beige", width=50, height=15) self.close_button = Button(root, text='===關 閉===', command=root.quit, bg='red', fg='white') self.label_blank.grid(row=0, column=0) self.label_step1.grid(row=1, column=0) self.label_baoleiji.grid(row=2, column=1) self.hostname_or_ip1.grid(row=2, column=2) self.label_blank.grid(row=2, column=3) self.lock1.grid(row=2, column=4) self.label_blank.grid(row=2, column=5) self.unlock1.grid(row=2, column=6) self.label_blank.grid(row=3, column=0) self.label_targethost.grid(row=3, column=1) self.hostname_or_ip2.grid(row=3, column=2) self.label_blank.grid(row=3, column=3) self.lock2.grid(row=3, column=4) self.label_blank.grid(row=3, column=5) self.unlock2.grid(row=3, column=6) self.label_blank.grid(row=4, column=0) self.label_step2.grid(row=5, column=0) self.label_upload.grid(row=6, column=1, sticky=E) self.select_file.grid(row=6, column=2) self.label_blank.grid(row=6, column=3) self.select_button.grid(row=6, column=4) self.upload_button.grid(row=7, column=2, sticky=W) self.cancel_button.grid(row=7, column=2, sticky=E) self.label_blank.grid(row=8, column=0) self.label_step3.grid(row=9, column=0) self.label_command_lujin.grid(row=10, column=1, sticky=E) self.select_command_file.grid(row=10, column=2) self.label_blank.grid(row=10, column=3) self.select_button1.grid(row=10, column=4) self.start_button.grid(row=12, column=2, sticky=W) self.stop_button.grid(row=12, column=2, sticky=E) self.label_step4.grid(row=14, sticky=W) self.label_overload_lujin.grid(row=15, column=1, sticky=E) self.select_overload_file.grid(row=15, column=2) self.label_blank.grid(row=15, column=3) self.select_button2.grid(row=15, column=4) self.label_overload__remote_lujin.grid(row=16, column=1, sticky=E) self.select_overload_remote_file.grid(row=16, column=2) self.update_button.grid(row=17, column=2, sticky=W) self.restart_button.grid(row=17, column=2, sticky=E) self.label_blank.grid(row=18, column=3) self.label_blank.grid(row=19, column=3) self.help_button.grid(row=20, column=2, sticky=W) self.close_button.grid(row=20, column=2, sticky=E) self.help_text.grid(row=21, column=2, sticky=W) def check_button(self, item, hi): if item == 1: text_cont = hi.get() hi.configure(state="disabled") else: hi.configure(state="normal") def selectfile(self, file_path): self.filename = tkFileDialog.askopenfilename(parent=root) file_path.delete(0, END) file_path.insert(0, self.filename) def selec_update_file(self, file_path): self.update_filename = tkFileDialog.askopenfilename(parent=root) file_path.delete(0, END) file_path.insert(0, self.update_filename) def cancel_file(self): self.select_file.delete(0, END) def upload_to_server(self): text_ip1 = self.hostname_or_ip1.get() text_ip2 = self.hostname_or_ip2.get() if text_ip1 == '' or text_ip2 == '': tkMessageBox.showwarning(title="警告", message="請先完成Step1,輸入主機名或者IP") else: targetfile = os.path.split(self.filename) lastword_file = targetfile[-1] upload_value = uploadfile.upload_ssh(text_ip1, self.filename, lastword_file) if upload_value != "": self.help_text.insert(INSERT, upload_value) uploadfile.remote_scp(text_ip1, text_ip2, lastword_file) def start_host(self): text_ip1 = self.hostname_or_ip1.get() text_ip2 = self.hostname_or_ip2.get() if text_ip1 == '' or text_ip2 == '': tkMessageBox.showwarning(title="警告", message="請先完成Step1,輸入主機名或者IP") else: host1 = 'qhiex@'+text_ip1 host2 = 'qhiex@'+text_ip2 fabpath = self.select_command_file.get() if fabpath == '': tkMessageBox.showwarning(title="警告", message="請選擇執行腳步路徑!") else: m=local('fab -f '+fabpath+' -g '+host1+' -H '+host2+' update_remotehost') self.help_text.insert(INSERT, m+"\n") def stop_host(self): text_ip1 = self.hostname_or_ip1.get() text_ip2 = self.hostname_or_ip2.get() if text_ip1 == '' or text_ip2 == '': tkMessageBox.showwarning(title="警告", message="請先完成Step1,輸入主機名或者IP") else: host1 = 'qhiex@'+text_ip1 host2 = 'qhiex@'+text_ip2 fabpath = self.select_command_file.get() if fabpath == '': tkMessageBox.showwarning(title="警告", message="請選擇執行腳步路徑!") else: m=local('fab -f '+fabpath+' -g '+host1+' -H '+host2+' stop_remotehost') self.help_text.insert(INSERT, m+"\n") def update_file(self): text_ip1 = self.hostname_or_ip1.get() text_ip2 = self.hostname_or_ip2.get() update_file_lujing = self.select_overload_file.get() fabpath = self.select_command_file.get() if text_ip1 == '' or text_ip2 == '' or update_file_lujing == '' or fabpath == '': tkMessageBox.showwarning(title="警告", message="請輸入主機名或者IP,並確保是否選擇了腳本文件以及更新文件!") else: targetfile = os.path.split(self.update_filename) lastword_file = targetfile[-1] upload_value = uploadfile.upload_ssh(text_ip1, self.update_filename, lastword_file) if upload_value != "": uploadfile.remote_scp(text_ip1, text_ip2, lastword_file) host1 = 'qhiex@'+text_ip1 host2 = 'qhiex@'+text_ip2 remote_path = self.select_overload_remote_file.get() m=local('fab -f '+fabpath+' -g '+host1+' -H '+host2+' update_file:'+lastword_file+','+remote_path, capture=True) self.help_text.insert(INSERT, m) def restart_host(self): text_ip1 = self.hostname_or_ip1.get() text_ip2 = self.hostname_or_ip2.get() if text_ip1 == '' or text_ip2 == '': tkMessageBox.showwarning(title="警告", message="請先完成Step1,輸入主機名或者IP") else: host1 = 'qhiex@'+text_ip1 host2 = 'qhiex@'+text_ip2 fabpath = self.select_command_file.get() if fabpath == '': tkMessageBox.showwarning(title="警告", message="請選擇執行腳步路徑!") else: local('fab -f '+fabpath+' -g '+host1+' -H '+host2+' restart_host') def help_t(self): self.help_text.insert(INSERT, "1.環境設定:本程序使用了python2.7,fabric,不具有的話,麻煩在百度或者google下載安裝\n") self.help_text.insert(INSERT, "2.該程序client端與server端已經打通了ssh通道,若是不知道怎麼創建本機的ssh-key," "能夠下載個git客戶端生成,並上傳到相關服務器\n") self.help_text.insert(END, "3.有問題能夠聯繫QQ:649081773,tel:13715165238") if __name__ == "__main__": app = Dilog_window_init() root.mainloop()
uploadfile.py
__author__ = 'samfeng' #coding=utf-8 import paramiko from os import path from sys import exit import getpass import mysql.connector, ConfigParser from mysql.connector import errorcode def con_mysql(host): configFeed = ConfigParser.ConfigParser() configFeed.read('conn.conf') connectuser = configFeed.get('user', 'user') connectp = configFeed.get('pa', 'password') connecthost = configFeed.get('host', 'host') connetdatabase = configFeed.get('database', 'database') try: cnx = mysql.connector.connect( user=connectuser, passwd=connectp, host=connecthost, database=connetdatabase ) except mysql.connector.Error as err: if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Something is wrong with your user name or password") elif err.errno == errorcode.ER_BAD_DB_ERROR: print("Database does not exists") else: print(err) c = cnx.cursor() c.execute("select passwd from hosta where inter_ip=%s", (host, )) p = c.fetchall() c.close() return p def upload_ssh(gatewayhost, localpath, remotefile): p = con_mysql(gatewayhost) p = ''.join(p[0]) t = paramiko.Transport((gatewayhost, 22)) t.connect(username="qhiex", password=p) sftp = paramiko.SFTPClient.from_transport(t) remotepath = '/xxx/xxx/xx/'+remotefile if path.exists(localpath): sftp.put(localpath, remotepath) return "upload success!" else: print("could not find local file!") t.close() def remote_scp(gatewayhost, targethost, remotefile): try: user_name = getpass.getuser() h = paramiko.SSHClient() h.set_missing_host_key_policy(paramiko.AutoAddPolicy()) h.connect(gatewayhost, username='qhiex', key_filename='C:\\Users\\'+user_name+'\\.ssh\\id_rsa') h.exec_command("scp /xxx/xxx/xx/"+remotefile+" qhiex@"+targethost+":/xxx/xxx/xxx/"+remotefile) h.close() except paramiko.AuthenticationException: print('Authentication failed!') print "could not ssh to remotehost!" exit(1)
在貼上醜陋的界面: