基于paramiko的文件批量分发和命令批量执行

    在实际工作环境中,有可能需要去运维百台服务器,甚至更多。以应用升级为例,对应用做升级操作,首先得停止应用服务,防止新的应用数据写入,并备份应用部署目录,然后替换成新的代码文件、配置文件等。替换完成后,启动应用服务。但是由于应用服务器数量过多,如果一台一台服务器去做升级,这会花费很多时间。这时,便可使用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执行效果如下:
基于paramiko的文件批量分发和命令批量执行
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. 新闻名称:基于paramiko的文件批量分发和命令批量执行
    链接地址:http://bzwzjz.com/article/isgphh.html