在实际工作环境中,有可能需要去运维百台服务器,甚至更多。以应用升级为例,对应用做升级操作,首先得停止应用服务,防止新的应用数据写入,并备份应用部署目录,然后替换成新的代码文件、配置文件等。替换完成后,启动应用服务。但是由于应用服务器数量过多,如果一台一台服务器去做升级,这会花费很多时间。这时,便可使用paramiko编写python脚本,让这些重复性的操作批量执行,去实现应用升级的自动化。这个小工具实现了在堡垒机模式和非堡机模式的运用。

1.maintool.py(控制整个脚本的执行),代码如下:

点击(此处)折叠或打开

#!/usr/bin/python
#coding:utf-8
import sys
######脚本执行操作提示
def login():
print """\033[1;34m
1:批量分发文件(非堡垒机模式)
2:批量执行命令(非堡垒机模式)
3:批量下载文件(非堡垒机模式)
4:单台执行命令(非堡垒机模式)
5:批量分发文件(堡垒机模式)
6:批量执行命令(堡垒机模式)
7:增加需要服务器(非堡垒机模式)
8:删除不需要服务器(非堡垒机模式)
9:查看当前服务器列表(非堡垒机模式)
10:退出\033[0m
"""
#######定义用户选择函数
def choice():
import operation,blhost_operation
while True:
choice=raw_input("\033[1;32minput your choice:\033[0m").strip()
choice_list = ['1','2','3','4','5','6','7','8','9','10','help','exit']
if choice not in choice_list:
print "\033[1;33mtry again!\033[0m"
continue
if choice == '1':
operation.SendFile()###非堡机模式下文件分发
login()
if choice == '2':
operation.ExecuteCmd()###非堡机模式下命令执行
login()
if choice == '3':
operation.DownloadFile()###非堡机模式下文件下载
login()
if choice == '4':
operation.SingleServer()###单台服务器操作
login()
if choice == '5':
blhost_operation.SendFile()###堡垒机模式下文件分发
login()
if choice == '6':
blhost_operation.ExecuteCmd()###堡垒机模式下命令执行
login()
if choice == '7':
operation.AddServerList()###增加服务器名单
if choice == '8':
operation.DeleteServerList()###删除服务器名单
if choice == '9':
operation.ShowServerList()###展示服务器名单
login()
if choice == '10' or choice == 'exit':###退出脚本操作
print "\033[1;31mThank you for your use!\033[0m"
sys.exit(0)
if choice == 'help':
login()
if __name__ == '__main__':
login()
choice()
maintool.py执行效果如下:

2.operation.py(定义非堡垒机模式下的相关操作),代码如下:

点击(此处)折叠或打开

#!/usr/bin/python
#coding:utf-8
import sys,time,threading
import getpass,commands
import paramiko,fabric
server_list=[]#HOSTNAME IP PWDROOT PWDWEBLOGIC PWDORACLE
result_dict={}
######读取文件内容,读取完成后关闭文件 f = open ('serverlist.txt')
for i in f.readlines():
server_list.append(i.split())
f.close()
######非堡垒机下文件的传送 def transfer(localpath,remotepath,hostname,username,password):
port = 22
try:
t = paramiko.Transport((hostname,port))
t.connect(username=username,password=password)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put(localpath,remotepath)
t.close()
result_dict[hostname] = hostname+"服务器文件传送完成"
print result_dict[hostname]
except Exception,e:
print str(e)
######定义文件下载函数 def download(remotepath,localpath,hostname,username,password):
port = 22
try:
t = paramiko.Transport((hostname,port))
t.connect(username=username,password=password)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get(remotepath,localpath)
t.close()
result_dict[hostname] = hostname+"服务器文件下载完成"
print result_dict[hostname]
except Exception,e:
print str(e)
######定义命令执行函数 def execmd(hostname,username,password,CMD):
paramiko.util.log_to_file('syslogin.log')###将用户登录服务器日志输出到syslogin.log
ssh = paramiko.SSHClient()###ssh登录服务器
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())###自动添加主机名及主机密钥到本地HostKeys对象,并将其保存,不依赖load_system_host_keys()的配置,即使~/.ssh/known_hosts不存在也不产生影响
ssh.connect(hostname=hostname,username=username,password=password)
stdin,stdout,stderr = ssh.exec_command(CMD)
result = stdout.read()
ssh.close()
result_dict[hostname] = hostname+"服务器命令执行结果如下:"+"\n"+result
print result_dict[hostname]
######执行结果打印 def result_dict_print():
global result_dict
while True:
if len(result_dict) == len(server_list):
break
print "\033[1;36m%s台服务器完成\033[0m" %(len(result_dict))
result_dict={}
######非保垒机模式下文件的分发 def SendFile():
while True:
username = raw_input("\033[1;32m请输入你选择要用于发送文件的用户[root/weblogic/oracle]:\033[0m").strip()
username_list = ['root','weblogic','oracle','\n','exit']
if username not in username_list:
print "\033[0;32minput error!Please try again!If you need exit,please input exit!\033[0m"
continue
if username == 'exit':
sys.exit()
localpath = raw_input("\033[1;32m本地文件(绝对路径):\033[0m").strip()
remotepath = raw_input("\033[1;32m服务器目的地址(绝对路径):\033[0m").strip()
if username == 'root':
for list in server_list:
p = threading.Thread(target=transfer,args=(localpath,remotepath,list[1],username,list[2],))
p.start()
for list in server_list:
p.join(timeout=1)
if username == 'weblogic' or username == '':
username = 'weblogic'
for list in server_list:
p = threading.Thread(target=transfer,args=(localpath,remotepath,list[1],username,list[3],))
p.start()
if username == 'oracle':
username = 'oracle'
for list in server_list:
p = threading.Thread(target=transfer,args=(localpath,remotepath,list[1],username,list[4],))
p.start()
result_dict_print()
break
######非堡垒机模式下文件的下载 def DownloadFile():
while True:
username = raw_input("\033[1;32m请输入你选择要用于下载文件的用户[root/weblogic/oracle]:\033[0m").strip()
username_list = ['root','weblogic','oracle','\n','exit']
if username not in username_list:
print "\033[1;32minput error!Please try again!If you need exit,please input exit!\033[0m"
continue
if username == 'exit':
sys.exit()
remotepath = raw_input("\033[1;32m远程文件(绝对路径):\033[0m").strip()
localpath = raw_input("\033[1;32m服务器目的地址(目录名,默认为/opt/zzx/python/bin):\033[0m").strip()
if localpath == '':
localpath = '/opt/zzx/python/bin'
localpath = localpath+"/"
print localpath
count = remotepath.count('/')
basename = remotepath.split('/')[count]
if username == 'root':
for list in server_list:
p = threading.Thread(target=download,args=(remotepath,localpath+list[1]+"_"+basename,list[1],username,list[2],))
p.start()
for list in server_list:
p.join(timeout=1)
if username == 'weblogic' or username == '':
username = 'weblogic'
for list in server_list:
localpath = result1+list[1]+"_"+result2
p = threading.Thread(target=download,args=(remotepath,localpath,list[1],username,list[3],))
p.start()
if username == 'oracle':
for list in server_list:
localpath = result1+list[1]+"_"+result2
p = threading.Thread(target=download,args=(remotepath,localpath,list[1],username,list[4],))
p.start()
result_dict_print()
break
######非堡垒机模式下命令的执行 def ExecuteCmd():
while True:
username = raw_input("\033[1;32m请输入你选择要用于执行命令的用户[root/weblogic/oracle]:\033[0m").strip()
username_list = ['root','weblogic','oracle','\n','exit']
if username not in username_list:
print "\033[1;32minput error!Please try again!If you need exit,please input exit!\033[0m"
continue
if username == 'exit':
sys.exit()
CMD = raw_input("\033[1;37m请输入要执行的命令(不能带引号):\033[0m").strip()
if CMD == 'exit':
return
if username == 'root':
for list in server_list:
p = threading.Thread(target=execmd,args=(list[1],username,list[2],CMD,))
p.start()
if username == 'weblogic' or username == '':
username = 'weblogic'
for list in server_list:
p = threading.Thread(target=execmd,args=(list[1],username,list[3],CMD))
p.start()
if username == 'oracle':
for list in server_list:
p = threading.Thread(target=execmd,args=(list[1],username,list[4],CMD))
p.start()
result_dict_print()
break
######单台服务器操作 def SingleServer():
IP = raw_input("\033[1;32m请输入要执行命令的服务器IP地址:\033[0m").strip()
username = raw_input("\033[1;32m请输入要执行命令的服务器用户名:\033[0m").strip()
password = getpass.getpass()
CMD = raw_input("\033[1;32m请输入要执行的命令(不能带引号):\033[0m").strip()
execmd(IP,username,password,CMD)
######服务器名单添加 def AddServerList():
hostname = raw_input("\033[1;32m请输入服务器名称(如localhost):\033[0m").strip()
if hostname == 'quit' or hostname == 'exit':
return
ip = raw_input("\033[1;32m请输入服务器IP:\033[0m").strip()
root_passwd = raw_input("\033[1;32m请输入服务器root用户密码:\033[0m").strip()
weblogic_passwd = raw_input("\033[1;32m请输入服务器weblogic用户密码:\033[0m").strip()
oracle_passwd = raw_input("\033[1;32m请输入服务器oracle用户密码:\033[0m").strip()
f = file('serverlist.txt','a')
f.write("%s %s %s %s %s\n"%(hostname,ip,root_passwd,weblogic_passwd,oracle_passwd))
f.close()
raw_input("\033[1;32m重新执行程序后生效(敲任意键退出)...\033[0m")
time.sleep(0.2)
sys.exit()
######服务器名单删除 def DeleteServerList():
IP = raw_input("\033[1;32m请输入要删除服务器IP:\033[0m").strip()
if IP == 'quit' or IP == 'exit':
return
status,result = commands.getstatusoutput("sed -i '/\<%s\>/'d ./serverlist.txt" % IP)
raw_input("\033[1;32m重新执行程序后生效(敲任意键退出)...\033[0m")
time.sleep(0.2)
sys.exit()
######服务器名单显示 def ShowServerList():
i = 0
f = open('serverlist.txt','rb')
for line in f.readlines():
print line.strip()
i = i+1
f.close
print "\n总共%s台服务器" % i3.blhost_operation.py(定义堡垒机模式下的相关操作),代码如下:

点击(此处)折叠或打开

#!/usr/bin/python
#coding:utf-8
import sys,time,threading
import getpass,commands,os
import paramiko,fabric
server_list=[]#HOSTNAME IP PWDROOT PWDWEBLOGIC PWDORACLE
result_dict={}
######读取文件内容,读取完成后关闭文件 f = open ('serverlist.txt')
for i in f.readlines():
server_list.append(i.split())
f.close()
######堡垒机下文件的传送 def transfer(bllocalpath,remotepath,blhostname,blusername,blpassword,hostname,username,password):
passinfo='\'s password: '
paramiko.util.log_to_file('blhost_upload.log')

ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())###自动添加主机名及主机密钥到本地HostKeys对象,并将其保存,不依赖load_system_host_keys()的配置,即使~/.ssh/known_hosts不存在也不产生影响
ssh.connect(hostname=blhostname,username=blusername,password=blpassword)

channel=ssh.invoke_shell()
channel.settimeout(100)
buff=''
resp=''
channel.send('scp '+bllocalpath+' '+username+'@'+hostname+':'+remotepath+'\n')
while not buff.endswith(passinfo):
try:
resp=channel.recv(9999)
except Exception,e:
print "Error info:receive nothing"
print str(e)
channel.close()
ssh.close()
sys.exit()
buff += resp
if not buff.find('yes/no')==-1:
channel.send('yes\n')
buff=''
buff=''
channel.send(password+'\n')
while not buff.endswith('# '):
resp=channel.recv(9999)
if not resp.find(passinfo)==-1:
print "Error info:Authentication failed."
print "Please confirm if your password is true!"
channel.close()
ssh.close()
sys.exit()
buff += resp
channel.close()
ssh.close()
result_dict[hostname] = hostname+"服务器文件传送完成"
print result_dict[hostname]
######堡垒机模式下命令执行 def execmd(blhostname,blusername,blpassword,hostname,username,password,CMD):
passinfo='\'s password: '
paramiko.util.log_to_file('blhost_syslogin.log')

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

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

buff=''
resp=''
channel.send('ssh '+username+'@'+hostname+'\n')
while not buff.endswith(passinfo):
try:
resp=channel.recv(9999)
except Exception,e:
print "fail to connect"
print "Error info: "+str(e)
channel.close()
ssh.close()
sys.exit()
buff += resp
if not buff.find('yes/no')==-1:
channel.send('yes\n')
buff=''
buff=''
channel.send(password+'\n')
while not buff.endswith('# '):
resp=channel.recv(9999)
if not resp.find(passinfo)==-1:
print "Error info:Authentication failed"
channel.close()
ssh.close()
sys.exit()
buff += resp
buff=''
channel.send('%s\n' % CMD)
try:
while not buff.endswith('# '):
resp=channel.recv(9999)
buff += resp
except Exception,e:
print "Error info:"+str(e)

result = buff
channel.close()
ssh.close()
result_dict[hostname] = hostname+"服务器命令执行结果如下:"+"\n"+result
print result_dict[hostname]
######执行结果打印 def result_dict_print():
global result_dict
while True:
if len(result_dict) == len(server_list):
break
print "\033[1;36m%s台服务器完成\033[0m" %(len(result_dict))
result_dict={}
######堡垒机模式下文件的批量分发 def SendFile():
while True:
blusername = raw_input("\033[1;32m请输入你选择要用于发送文件的堡垒机用户[root/weblogic/oracle]:\033[0m").strip()
blusername_list = ['root','weblogic','oracle','','exit']
if blusername not in blusername_list:
print "\033[0;32minput error!Please try again!If you need exit,please input exit!\033[0m"
continue
if blusername == 'exit':
return
blhostname=raw_input("\033[1;32m请输入你选择要用于发送文件的堡垒机IP:\033[0m").strip()
print "\033[1;32m请输入你选择要用于发送文件的堡垒机密码:\033[0m"
blpassword=getpass.getpass()
username=raw_input("\033[1;32m请输入你选择要用于接收文件的用户[root/weblogic/oracle]:\033[0m").strip()
bllocalpath=raw_input("\033[1;32m堡垒机本地文件(绝对路径):\033[0m").strip()
remotepath=raw_input("\033[1;32m服务器目的地址(绝对路径):\033[0m").strip()
if blusername == 'root':
for list in server_list:
p = threading.Thread(target=transfer,args=(bllocalpath,remotepath,blhostname,blusername,blpassword,list[1],username,list[2],))
p.start()
for list in server_list:
p.join(timeout=1)
if blusername == 'weblogic' or blusername == '':
blusername = 'weblogic'
for list in server_list:
p = threading.Thread(target=transfer,args=(bllocalpath,remotepath,blhostname,blusername,blpassword,list[1],username,list[3],))
p.start()
if blusername == 'oracle':
for list in server_list:
p = threading.Thread(target=transfer,args=(bllocalpath,remotepath,blhostname,blusername,blpassword,list[1],username,list[4],))
p.start()
result_dict_print()
break
######堡垒机模式下命令的批量执行 def ExecuteCmd():
while True:
blusername = raw_input("\033[1;32m请输入你选择要用于跳转的堡垒机用户[root/weblogic/oracle]:\033[0m").strip()
blusername_list = ['root','weblogic','oracle','','exit']
if blusername not in blusername_list:
print "\033[0;32minput error!Please try again!If you need exit,please input exit!\033[0m"
continue
if blusername == 'exit':
return
blhostname=raw_input("\033[1;32m请输入你选择要用于跳转的堡垒机IP:\033[0m").strip()
print "\033[1;32m请输入你选择要用于跳转的堡垒机密码:\033[0m"
blpassword=getpass.getpass()
username=raw_input("\033[1;32m请输入你选择要用于执行命令的用户[root/weblogic/oracle]:\033[0m").strip()
CMD = raw_input("\033[1;37m请输入要执行的命令(不能带引号):\033[0m").strip()
if CMD == 'exit':
return
if blusername == 'root':
for list in server_list:
p = threading.Thread(target=execmd,args=(blhostname,blusername,blpassword,list[1],username,list[2],CMD,))
p.start()
if username == 'weblogic' or username == '':
username = 'weblogic'
for list in server_list:
p = threading.Thread(target=execmd,args=(blhostname,blusername,blpassword,list[1],username,list[3],CMD,))
p.start()
if username == 'oracle':
for list in server_list:
p = threading.Thread(target=execmd,args=(blhostname,blusername,blpassword,list[1],username,list[4],CMD,))
p.start()
result_dict_print()
break 至此,这个python小工具制作完成。