基於paramiko的檔案批次分發和命令批次執行

RedCompu93發表於2018-06-09
    在實際工作環境中,有可能需要去運維百臺伺服器,甚至更多。以應用升級為例,對應用做升級操作,首先得停止應用服務,防止新的應用資料寫入,並備份應用部署目錄,然後替換成新的程式碼檔案、配置檔案等。替換完成後,啟動應用服務。但是由於應用伺服器數量過多,如果一臺一臺伺服器去做升級,這會花費很多時間。這時,便可使用paramiko編寫python指令碼,讓這些重複性的操作批次執行,去實現應用升級的自動化。這個小工具實現了在堡壘機模式和非堡機模式的運用。

1.maintool.py
(控制整個指令碼的執行),程式碼如下:

點選(此處)摺疊或開啟

  1. #!/usr/bin/python
  2. #coding:utf-8
  3. import sys
  4. ######指令碼執行操作提示
  5. def login():
  6.     print """\033[1;34m
  7.     1:批次分發檔案(非堡壘機模式)
  8.     2:批次執行命令(非堡壘機模式)
  9.     3:批次下載檔案(非堡壘機模式)
  10.     4:單臺執行命令(非堡壘機模式)
  11.     5:批次分發檔案(堡壘機模式)
  12.     6:批次執行命令(堡壘機模式)
  13.     7:增加需要伺服器(非堡壘機模式)
  14.     8:刪除不需要伺服器(非堡壘機模式)
  15.     9:檢視當前伺服器列表(非堡壘機模式)
  16.     10:退出\033[0m
  17.     """
  18. #######定義使用者選擇函式
  19. def choice():
  20.     import operation,blhost_operation
  21.     while True:
  22.         choice raw_input("\033[1;32minput your choice:\033[0m").strip()
  23.         choice_list = ['1','2','3','4','5','6','7','8','9','10','help','exit']
  24.         if choice not in choice_list:
  25.             print "\033[1;33mtry again!\033[0m"
  26.             continue
  27.         if choice == '1':
  28.             operation.SendFile()###非堡機模式下檔案分發
  29.      login()
  30.         if choice == '2':
  31.             operation.ExecuteCmd()###非堡機模式下命令執行
  32.             login()
  33.         if choice == '3':
  34.             operation.DownloadFile()###非堡機模式下檔案下載
  35.             login()
  36.         if choice == '4':
  37.             operation.SingleServer()###單臺伺服器操作
  38.             login()
  39.         if choice == '5':
  40.             blhost_operation.SendFile()###堡壘機模式下檔案分發
  41.             login()
  42.         if choice == '6':
  43.             blhost_operation.ExecuteCmd()###堡壘機模式下命令執行
  44.             login()
  45.         if choice == '7':
  46.             operation.AddServerList()###增加伺服器名單
  47.         if choice == '8':
  48.             operation.DeleteServerList()###刪除伺服器名單
  49.         if choice == '9':
  50.             operation.ShowServerList()###展示伺服器名單
  51.             login()
  52.         if choice == '10' or choice == 'exit':###退出指令碼操作
  53.             print "\033[1;31mThank you for your use!\033[0m"
  54.             sys.exit(0)
  55.         if choice == 'help':
  56.             login()
  57. if __name__ == '__main__':
  58.     login()
  59.     choice()

maintool.py執行效果如下:

2.operation.py(定義非堡壘機模式下的相關操作),程式碼如下:

點選(此處)摺疊或開啟

  1. #!/usr/bin/python
  2. #coding:utf-8
  3. import sys,time,threading
  4. import getpass,commands
  5. import paramiko,fabric
  6. server_list=[]        #HOSTNAME IP PWDROOT PWDWEBLOGIC PWDORACLE
  7. result_dict={}
  8. ######讀取檔案內容,讀取完成後關閉檔案
  9. f = open ('serverlist.txt')
  10. for i in f.readlines():
  11.     server_list.append(i.split())
  12. f.close()
  13. ######非堡壘機下檔案的傳送
  14. def transfer(localpath,remotepath,hostname,username,password):
  15.     port = 22
  16.     try:
  17.         t = paramiko.Transport((hostname,port))
  18.         t.connect(username=username,password=password)
  19.         sftp = paramiko.SFTPClient.from_transport(t)
  20.         sftp.put(localpath,remotepath)
  21.         t.close()
  22.         result_dict[hostname] = hostname+"伺服器檔案傳送完成"
  23.         print result_dict[hostname]
  24.     except Exception,e:
  25.         print str(e)
  26. ######定義檔案下載函式
  27. def download(remotepath,localpath,hostname,username,password):
  28.     port = 22
  29.     try:
  30.         t = paramiko.Transport((hostname,port))
  31.         t.connect(username=username,password=password)
  32.         sftp = paramiko.SFTPClient.from_transport(t)
  33.         sftp.get(remotepath,localpath)
  34.         t.close()
  35.         result_dict[hostname] = hostname+"伺服器檔案下載完成"
  36.         print result_dict[hostname]
  37.     except Exception,e:
  38.         print str(e)
  39. ######定義命令執行函式
  40. def execmd(hostname,username,password,CMD):
  41.     paramiko.util.log_to_file('syslogin.log')###將使用者登入伺服器日誌輸出到syslogin.log
  42.     ssh = paramiko.SSHClient()###ssh登入伺服器
  43.     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())###自動新增主機名及主機金鑰到本地HostKeys物件,並將其儲存,不依賴load_system_host_keys()的配置,即使~/.ssh/known_hosts不存在也不產生影響
  44.     ssh.connect(hostname=hostname,username=username,password=password)
  45.     stdin,stdout,stderr = ssh.exec_command(CMD)
  46.     result = stdout.read()
  47.     ssh.close()
  48.     result_dict[hostname] = hostname+"伺服器命令執行結果如下:"+"\n"+result
  49.     print result_dict[hostname]
  50. ######執行結果列印
  51. def result_dict_print():
  52.     global result_dict
  53.     while True:
  54.         if len(result_dict) == len(server_list):
  55.             break
  56.     print "\033[1;36m%s臺伺服器完成\033[0m" %(len(result_dict))
  57.     result_dict {}
  58. ######非保壘機模式下檔案的分發
  59. def SendFile():
  60.     while True:
  61.         username = raw_input("\033[1;32m請輸入你選擇要用於傳送檔案的使用者[root/weblogic/oracle]:\033[0m").strip()
  62.         username_list = ['root','weblogic','oracle','\n','exit']
  63.         if username not in username_list:
  64.             print "\033[0;32minput error!Please try again!If you need exit,please input exit!\033[0m"
  65.             continue
  66.         if username == 'exit':
  67.             sys.exit()
  68.         localpath = raw_input("\033[1;32m本地檔案(絕對路徑):\033[0m").strip()
  69.         remotepath = raw_input("\033[1;32m伺服器目的地址(絕對路徑):\033[0m").strip()
  70.         if username == 'root':
  71.             for list in server_list:
  72.         p = threading.Thread(target=transfer,args=(localpath,remotepath,list[1],username,list[2],))
  73.         p.start()
  74.             for list in server_list:
  75.             p.join(timeout=1)
  76.         if username == 'weblogic' or username == '':
  77.             username = 'weblogic'
  78.             for list in server_list:
  79.                 p = threading.Thread(target=transfer,args=(localpath,remotepath,list[1],username,list[3],))
  80.                 p.start()
  81.         if username == 'oracle':
  82.             username = 'oracle'
  83.             for list in server_list:
  84.                 p = threading.Thread(target=transfer,args=(localpath,remotepath,list[1],username,list[4],))
  85.                 p.start()
  86.         result_dict_print()
  87.         break
  88. ######非堡壘機模式下檔案的下載
  89. def DownloadFile():
  90.     while True:
  91.         username = raw_input("\033[1;32m請輸入你選擇要用於下載檔案的使用者[root/weblogic/oracle]:\033[0m").strip()
  92.         username_list = ['root','weblogic','oracle','\n','exit']
  93.         if username not in username_list:
  94.             print "\033[1;32minput error!Please try again!If you need exit,please input exit!\033[0m"
  95.             continue
  96.         if username == 'exit':
  97.             sys.exit()
  98.         remotepath = raw_input("\033[1;32m遠端檔案(絕對路徑):\033[0m").strip()
  99.         localpath = raw_input("\033[1;32m伺服器目的地址(目錄名,預設為/opt/zzx/python/bin):\033[0m").strip()
  100.         if localpath == '':
  101.             localpath = '/opt/zzx/python/bin'
  102.         localpath = localpath+"/"
  103.         print localpath
  104.         count = remotepath.count('/')
  105.         basename = remotepath.split('/')[count]
  106.         if username == 'root':
  107.             for list in server_list:
  108.                 p = threading.Thread(target=download,args=(remotepath,localpath+list[1]+"_"+basename,list[1],username,list[2],))
  109.                 p.start()
  110.             for list in server_list:
  111.                 p.join(timeout=1)
  112.         if username == 'weblogic' or username == '':
  113.             username = 'weblogic'
  114.             for list in server_list:
  115.                 localpath = result1+list[1]+"_"+result2
  116.                 p = threading.Thread(target=download,args=(remotepath,localpath,list[1],username,list[3],))
  117.                 p.start()
  118.         if username == 'oracle':
  119.             for list in server_list:
  120.                 localpath = result1+list[1]+"_"+result2
  121.                 p = threading.Thread(target=download,args=(remotepath,localpath,list[1],username,list[4],))
  122.                 p.start()
  123.         result_dict_print()
  124.         break
  125. ######非堡壘機模式下命令的執行
  126. def ExecuteCmd():
  127.     while True:
  128.         username = raw_input("\033[1;32m請輸入你選擇要用於執行命令的使用者[root/weblogic/oracle]:\033[0m").strip()
  129.         username_list = ['root','weblogic','oracle','\n','exit']
  130.         if username not in username_list:
  131.             print "\033[1;32minput error!Please try again!If you need exit,please input exit!\033[0m"
  132.             continue
  133.         if username == 'exit':
  134.             sys.exit()
  135.         CMD = raw_input("\033[1;37m請輸入要執行的命令(不能帶引號):\033[0m").strip()
  136.         if CMD == 'exit':
  137.             return
  138.         if username == 'root':
  139.             for list in server_list:
  140.                 p = threading.Thread(target=execmd,args=(list[1],username,list[2],CMD,))
  141.                 p.start()
  142.         if username == 'weblogic' or username == '':
  143.             username = 'weblogic'
  144.             for list in server_list:
  145.                 p = threading.Thread(target=execmd,args=(list[1],username,list[3],CMD))
  146.                 p.start()
  147.         if username == 'oracle':
  148.             for list in server_list:
  149.                 p = threading.Thread(target=execmd,args=(list[1],username,list[4],CMD))
  150.                 p.start()
  151.         result_dict_print()
  152.         break
  153. ######單臺伺服器操作
  154. def SingleServer():
  155.     IP = raw_input("\033[1;32m請輸入要執行命令的伺服器IP地址:\033[0m").strip()
  156.     username = raw_input("\033[1;32m請輸入要執行命令的伺服器使用者名稱:\033[0m").strip()
  157.     password = getpass.getpass()
  158.     CMD = raw_input("\033[1;32m請輸入要執行的命令(不能帶引號):\033[0m").strip()
  159.     execmd(IP,username,password,CMD)
  160. ######伺服器名單新增
  161. def AddServerList():
  162.     hostname = raw_input("\033[1;32m請輸入伺服器名稱(如localhost):\033[0m").strip()
  163.     if hostname == 'quit' or hostname == 'exit':
  164.         return
  165.     ip = raw_input("\033[1;32m請輸入伺服器IP:\033[0m").strip()
  166.     root_passwd = raw_input("\033[1;32m請輸入伺服器root使用者密碼:\033[0m").strip()
  167.     weblogic_passwd = raw_input("\033[1;32m請輸入伺服器weblogic使用者密碼:\033[0m").strip()
  168.     oracle_passwd = raw_input("\033[1;32m請輸入伺服器oracle使用者密碼:\033[0m").strip()    
  169.     f = file('serverlist.txt','a')
  170.     f.write("%s %s %s %s %s\n"%(hostname,ip,root_passwd,weblogic_passwd,oracle_passwd))
  171.     f.close()
  172.     raw_input("\033[1;32m重新執行程式後生效(敲任意鍵退出)...\033[0m")
  173.     time.sleep(0.2)
  174.     sys.exit()
  175. ######伺服器名單刪除
  176. def DeleteServerList():
  177.     IP = raw_input("\033[1;32m請輸入要刪除伺服器IP:\033[0m").strip()
  178.     if IP == 'quit' or IP == 'exit':
  179.         return
  180.     status,result = commands.getstatusoutput("sed -i '/\<%s\>/'d ./serverlist.txt" % IP)
  181.     raw_input("\033[1;32m重新執行程式後生效(敲任意鍵退出)...\033[0m")
  182.     time.sleep(0.2)
  183.     sys.exit()
  184. ######伺服器名單顯示
  185. def ShowServerList():
  186.     i = 0
  187.     f = open('serverlist.txt','rb')
  188.     for line in f.readlines():
  189.         print line.strip()
  190.         i = i+1
  191.     f.close
  192.     print "\n總共%s臺伺服器" % i
3.blhost_operation.py(定義堡壘機模式下的相關操作),程式碼如下:

點選(此處)摺疊或開啟

  1. #!/usr/bin/python
  2. #coding:utf-8
  3. import sys,time,threading
  4. import getpass,commands,os
  5. import paramiko,fabric
  6. server_list=[]        #HOSTNAME IP PWDROOT PWDWEBLOGIC PWDORACLE
  7. result_dict={}
  8. ######讀取檔案內容,讀取完成後關閉檔案
  9. f = open ('serverlist.txt')
  10. for i in f.readlines():
  11.     server_list.append(i.split())
  12. f.close()
  13. ######堡壘機下檔案的傳送
  14. def transfer(bllocalpath,remotepath,blhostname,blusername,blpassword,hostname,username,password):
  15.     passinfo='\'s password: '
  16.     paramiko.util.log_to_file('blhost_upload.log')

  17.     ssh=paramiko.SSHClient()
  18.     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())###自動新增主機名及主機金鑰到本地HostKeys物件,並將其儲存,不依賴load_system_host_keys()的配置,即使~/.ssh/known_hosts不存在也不產生影響
  19.     ssh.connect(hostname=blhostname,username=blusername,password=blpassword)

  20.     channel=ssh.invoke_shell()
  21.     channel.settimeout(100)
  22.     buff=''
  23.     resp=''
  24.     channel.send('scp '+bllocalpath+' '+username+'@'+hostname+':'+remotepath+'\n')
  25.     while not buff.endswith(passinfo):
  26.         try:
  27.             resp=channel.recv(9999)
  28.         except Exception,e:
  29.             print "Error info:receive nothing"
  30.             print str(e)
  31.             channel.close()
  32.             ssh.close()
  33.             sys.exit()
  34.         buff += resp
  35.         if not buff.find('yes/no')==-1:
  36.             channel.send('yes\n')
  37.             buff=''
  38.     buff=''
  39.     channel.send(password+'\n')
  40.     while not buff.endswith('# '):
  41.         resp=channel.recv(9999)
  42.         if not resp.find(passinfo)==-1:
  43.             print "Error info:Authentication failed."
  44.             print "Please confirm if your password is true!"
  45.             channel.close()
  46.             ssh.close()
  47.             sys.exit()
  48.         buff += resp
  49.     channel.close()
  50.     ssh.close()
  51.     result_dict[hostname] = hostname+"伺服器檔案傳送完成"
  52.     print result_dict[hostname]
  53. ######堡壘機模式下命令執行
  54. def execmd(blhostname,blusername,blpassword,hostname,username,password,CMD):
  55.     passinfo='\'s password: '
  56.     paramiko.util.log_to_file('blhost_syslogin.log')

  57.     ssh=paramiko.SSHClient()
  58.     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  59.     ssh.connect(hostname=blhostname,username=blusername,password=blpassword)

  60.     channel=ssh.invoke_shell()
  61.     channel.settimeout(100)

  62.     buff=''
  63.     resp=''
  64.     channel.send('ssh '+username+'@'+hostname+'\n')
  65.     while not buff.endswith(passinfo):
  66.         try:
  67.             resp=channel.recv(9999)
  68.         except Exception,e:
  69.             print "fail to connect"
  70.             print "Error info: "+str(e)
  71.             channel.close()
  72.             ssh.close()
  73.             sys.exit()
  74.         buff += resp
  75.         if not buff.find('yes/no')==-1:
  76.             channel.send('yes\n')
  77.             buff=''
  78.     buff=''
  79.     channel.send(password+'\n')
  80.     while not buff.endswith('# '):
  81.         resp=channel.recv(9999)
  82.         if not resp.find(passinfo)==-1:
  83.             print "Error info:Authentication failed"
  84.             channel.close()
  85.             ssh.close()
  86.             sys.exit()
  87.         buff += resp
  88.     buff=''
  89.     channel.send('%s\n' % CMD)
  90.     try:
  91.         while not buff.endswith('# '):
  92.             resp=channel.recv(9999)
  93.             buff += resp
  94.     except Exception,e:
  95.         print "Error info:"+str(e)

  96.     result = buff
  97.     channel.close()
  98.     ssh.close()
  99.     result_dict[hostname] = hostname+"伺服器命令執行結果如下:"+"\n"+result
  100.     print result_dict[hostname]
  101. ######執行結果列印
  102. def result_dict_print():
  103.     global result_dict
  104.     while True:
  105.         if len(result_dict) == len(server_list):
  106.             break
  107.     print "\033[1;36m%s臺伺服器完成\033[0m" %(len(result_dict))
  108.     result_dict={}
  109. ######堡壘機模式下檔案的批次分發
  110. def SendFile():
  111.     while True:
  112.         blusername = raw_input("\033[1;32m請輸入你選擇要用於傳送檔案的堡壘機使用者[root/weblogic/oracle]:\033[0m").strip()
  113.         blusername_list = ['root','weblogic','oracle','','exit']
  114.         if blusername not in blusername_list:
  115.             print "\033[0;32minput error!Please try again!If you need exit,please input exit!\033[0m"
  116.             continue
  117.         if blusername == 'exit':
  118.             return
  119.         blhostname=raw_input("\033[1;32m請輸入你選擇要用於傳送檔案的堡壘機IP:\033[0m").strip()
  120.         print "\033[1;32m請輸入你選擇要用於傳送檔案的堡壘機密碼:\033[0m"
  121.         blpassword=getpass.getpass()
  122.         username=raw_input("\033[1;32m請輸入你選擇要用於接收檔案的使用者[root/weblogic/oracle]:\033[0m").strip()
  123.         bllocalpath=raw_input("\033[1;32m堡壘機本地檔案(絕對路徑):\033[0m").strip()
  124.         remotepath=raw_input("\033[1;32m伺服器目的地址(絕對路徑):\033[0m").strip()
  125.         if blusername == 'root':
  126.             for list in server_list:
  127.         p = threading.Thread(target=transfer,args=(bllocalpath,remotepath,blhostname,blusername,blpassword,list[1],username,list[2],))
  128.         p.start()
  129.             for list in server_list:
  130.             p.join(timeout=1)
  131.         if blusername == 'weblogic' or blusername == '':
  132.             blusername = 'weblogic'
  133.             for list in server_list:
  134.                 p = threading.Thread(target=transfer,args=(bllocalpath,remotepath,blhostname,blusername,blpassword,list[1],username,list[3],))
  135.                 p.start()
  136.         if blusername == 'oracle':
  137.             for list in server_list:
  138.                 p = threading.Thread(target=transfer,args=(bllocalpath,remotepath,blhostname,blusername,blpassword,list[1],username,list[4],))
  139.                 p.start()
  140.         result_dict_print()
  141.         break
  142. ######堡壘機模式下命令的批次執行
  143. def ExecuteCmd():
  144.     while True:
  145.         blusername = raw_input("\033[1;32m請輸入你選擇要用於跳轉的堡壘機使用者[root/weblogic/oracle]:\033[0m").strip()
  146.         blusername_list = ['root','weblogic','oracle','','exit']
  147.         if blusername not in blusername_list:
  148.             print "\033[0;32minput error!Please try again!If you need exit,please input exit!\033[0m"
  149.             continue
  150.         if blusername == 'exit':
  151.             return
  152.         blhostname=raw_input("\033[1;32m請輸入你選擇要用於跳轉的堡壘機IP:\033[0m").strip()
  153.         print "\033[1;32m請輸入你選擇要用於跳轉的堡壘機密碼:\033[0m"
  154.         blpassword=getpass.getpass()
  155.         username=raw_input("\033[1;32m請輸入你選擇要用於執行命令的使用者[root/weblogic/oracle]:\033[0m").strip()
  156.         CMD = raw_input("\033[1;37m請輸入要執行的命令(不能帶引號):\033[0m").strip()
  157.         if CMD == 'exit':
  158.             return
  159.         if blusername == 'root':
  160.             for list in server_list:
  161.                 p = threading.Thread(target=execmd,args=(blhostname,blusername,blpassword,list[1],username,list[2],CMD,))
  162.                 p.start()
  163.         if username == 'weblogic' or username == '':
  164.             username = 'weblogic'
  165.             for list in server_list:
  166.                 p = threading.Thread(target=execmd,args=(blhostname,blusername,blpassword,list[1],username,list[3],CMD,))
  167.                 p.start()
  168.         if username == 'oracle':
  169.             for list in server_list:
  170.                 p = threading.Thread(target=execmd,args=(blhostname,blusername,blpassword,list[1],username,list[4],CMD,))
  171.                 p.start()
  172.         result_dict_print()
  173.         break
至此,這個python小工具製作完成。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31541436/viewspace-2155896/,如需轉載,請註明出處,否則將追究法律責任。

相關文章