#!/usr/bin/python2.7#coding=utf-8'''Created on Oct 19@author wangyunhua@smeyun.com Update Version TO WanVersion 1.1'''import osimport timeimport MySQLdbimport jsonimport loggingimport paramikoimport traceback as tbfrom argparse import ArgumentParserl = logging.getLogger('online')#获取时间用于打包备份命名D_TIME = time.strftime('%Y%m%d%H%M')#作为结果输出logs = []#获取脚本当前目录cfd = os.path.dirname(os.path.abspath(__file__))SystemUpdatePath="/data/BusinesstoCustomer/program/"update_service = []Service_Names = []GROUPS_Names = []result=[]MYSQLHOST='127.0.0.1'MYSQLUSER='root'MYSQLPASSWD='Feng!1900'Version_Url='http://192.168.200.141:8557/program/'def Server_sql():conn = MySQLdb.connect(host=MYSQLHOST,user=MYSQLUSER,passwd=MYSQLPASSWD,db='ccdb')curs = conn.cursor()try:curs.execute('''select d.servername,d.SD_path,e.serverhosts,e.SI_path,g.Jenkins_name,e.SL_status,e.Ssystem_class,f.muser,f.mpass,f.rpass,f.wuser,f.muserkey from t_server_ID_name d,t_server_list e,t_password f,t_jenkins_server_list g where e.serverID = d.serverID and e.servername = g.servername and e.serverhosts = f.ip and e.SL_status =1;''')conn.commit()data = curs.fetchall()#print u'fetchall()返回的数据:',dataconn.close()jsonData = []for row in data:result = {}result['servername'] = str(row[0])result['SD_path'] = str(row[1])result['serverhosts'] = row[2]result['SI_path'] = str(row[3])result['Jenkins_name'] = str(row[4])result['SL_status'] = str(row[5])result['Ssystem_class'] = str(row[6])result['muser'] = str(row[7])result['mpass'] = str(row[8])result['rpass'] = str(row[9])result['wuser'] = str(row[10])result['muserkey'] = str(row[11])jsonData.append(result)#l.debug('转换为列表字典的原始数据 : %r',jsonData)return json.dumps(jsonData)except:print 'MySQL connect fail...'else:#使用json.dumps将数据转换为json格式,json.dumps方法默认会输出成这种格式"u5377u76aeu6298u6263",加ensure_ascii=False,则能够防止中文乱码。#JSON采用完全独立于语言的文本格式,事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。#json.dumps()是将原始数据转为json(其中单引号会变为双引号),而json.loads()是将json转为原始数据。jsondatar=json.dumps(jsonData,ensure_ascii=False,sort_keys=True)#去除首尾的中括号return jsondatar[1:len(jsondatar)-1]def pack(ob,webnames):#取出相关服务器信息和状态file_data=json.loads(Server_sql())for wname in webnames:for aa in file_data:for obi in ob:if aa['servername'] == wname and aa['Ssystem_class'] == obi:service_object = services(aa['servername'],aa['SD_path'],aa['serverhosts'],aa['SI_path'],aa['Jenkins_name'],aa['SL_status'],aa['Ssystem_class'],aa['muser'],aa['mpass'],aa['rpass'],aa['wuser'],aa['muserkey'])update_service.append(service_object)def pack_info():#取出相关服务器信息和状态file_data=json.loads(Server_sql())for aa in file_data:service_name = aa['servername']groups_name = aa['Ssystem_class']Service_Names.append(service_name)Service_Names.append('all')GROUPS_Names.append(str(groups_name))GROUPS_Names.append('all')def scall(CMD_LINE):'''linux shell '''l.debug('CMD_LINE : %r',CMD_LINE)return call(CMD_LINE,shell=True)def os_system(cmd):result = os.popen(cmd)res = result.read()#for line in res.splitlines():#print linereturn res.splitlines()#封装的自定义打印模块def head_print():print ' 33[1;31;40m'#print '*' * 50#print ' '#封装的自定义打印模块def tail_print():#print ' '#print '*' * 50print ' 33[0m'#输出操作结果def output_result():head_print()for count in range(len(logs)):print " "for content in logs[count]:if 'MD5校验成功!' in content:print contentbreakprint contenttail_print()class services:def __init__(self,servername,SD_path,serverhosts,SI_path,Jenkins_name,SL_status,Ssystem_class,muser,mpass,rpass,wuser,muserkey):self.servername = servernameself.SD_path = SD_pathself.SI_path = SI_pathself.serverhosts = serverhostsself.Jenkins_name = Jenkins_nameself.SL_status = SL_statusself.Ssystem_class = Ssystem_classself.muser = muserself.mpass = mpassself.rpass = rpassself.wuser = wuserself.muserkey = muserkeyself.LOG_PATH = '/data/logs'self.SPRINT_PATH = '/tmp/'def connect(self,cmd):s=paramiko.SSHClient()s.load_system_host_keys()s.set_missing_host_key_policy(paramiko.AutoAddPolicy())if 'pro' in self.Ssystem_class:pkey = paramiko.RSAKey.from_private_key_file(self.muserkey)s.connect(hostname=self.serverhosts,port=22,username=self.muser,pkey=pkey,allow_agent=False)else:s.connect(hostname=self.serverhosts,port=22,username=self.muser, password=self.mpass,allow_agent=False,look_for_keys=False)if self.muser != 'root':ssh = s.invoke_shell()time.sleep(0.1)ssh.send('su - ')buff = ''while not buff.endswith('Password: '):resp = ssh.recv(9999)buff +=respssh.send(self.rpass)ssh.send(' ')buff = ''while not buff.endswith('# '):resp = ssh.recv(9999)buff +=respssh.send(cmd)ssh.send(' ')buff = ''while not buff.endswith('# '):resp = ssh.recv(9999)buff +=resps.close()result = buffelse:stdin, stdout, stderr = s.exec_command(cmd)result = stdout.read()s.close()l.debug('result %r',result)print self.serverhosts, cmdreturn result#关闭远端服务器tomcatdef test_remote(self):#关闭远端进程shl='''ifconfig eth0|grep inet'''l.debug('%r',shl)self.connect(cmd=shl)def stop_prcee(self):shl='''pkill -f %(name)s'''%{'name':self.servername}shl2='''ps aux|grep %(name)s|grep -v grep'''%{'name':self.servername}l.debug('%r',shl)l.debug('%r',shl2)self.connect(cmd=shl)self.connect(cmd=shl2)def start_prcee(self):'''su - user -c'''if self.wuser == 'root':shl='''/usr/bin/sh -l %(path)s/bin/start.sh '''%{'path':self.SI_path}else:shl='''runuser -l %(user)s -c "/usr/bin/sh -l %(path)s/bin/start.sh" '''%{'path':self.SI_path,'user':self.wuser}#shl='''su -c %(user)s "/usr/bin/sh -l %(path)s/bin/start.sh" '''%{'path':self.SI_path,'user':self.wuser}shl2='''ps aux|grep %(name)s|grep -v grep'''%{'name':self.servername}l.debug('%r',shl)l.debug('%r',shl2)self.connect(cmd=shl)self.connect(cmd=shl2)def ps_prcee(self):shl='''ps aux|grep %(name)s|grep -v grep'''%{'name':self.servername}l.debug('%r',shl)self.connect(cmd=shl)def chown_set(self):sh3 = '''chown -R %s %s''' %(self.wuser,self.SPRINT_PATH)sh1 = '''chown -R %s %s''' %(self.wuser,self.SI_path)sh2 = '''chown -R %s %s''' %(self.wuser,self.LOG_PATH)self.connect(cmd=sh3)self.connect(cmd=sh2)self.connect(cmd=sh1)def get_file(self):shl='''wget -NP %s %s'''%(self.SI_path+'/lib/',Version_Url+self.servername+'/'+self.Jenkins_name)l.debug('%r',shl)self.connect(cmd=shl)def get_md5(self):shl1='''/usr/bin/md5sum %s |cut -d ' ' -f1'''%(self.SD_path +'/' +self.Jenkins_name)local_md5 = os_system(shl1)[0]l.debug('local_md5 %r',local_md5)shl='''/usr/bin/md5sum %s |cut -d ' ' -f1'''%(self.SI_path +'/lib/'+self.Jenkins_name)remote_md5 = self.connect(cmd=shl).split()[8]l.debug('remote_md5 %r',remote_md5)print self.Jenkins_nameprint "本地文件MD5",local_md5print "远端文件MD5",remote_md5return cmp(local_md5,remote_md5)def back_file(self):shl1="if [ ! -d %s/lib/backup/ ];then mkdir %s/lib/backup/;fi" %(self.SI_path,self.SI_path)shl='''scp %s %s'''%(self.SI_path +'/lib/'+self.Jenkins_name,self.SI_path +'/lib/backup/'+self.Jenkins_name+'_%s'%D_TIME)l.debug('%r',shl)self.connect(cmd=shl1)self.connect(cmd=shl)#检测参数,执行操作def handle(args):logging.basicConfig(format="%(message)s")l.level = logging.INFOif args.verbose:l.level =logging.DEBUGop = args.operationob = args.objectwebnames = args.webnamess = servicesif 'all' in webnames:pack_info()Service_Names.remove('all')webname = set(Service_Names)pack(ob,webname)else:pack(ob,webnames)if not op:'''利用列表的方式实现swith功能'''comlist = ['stop','scp','ps','start',]else:comlist = [op]if op == 'test':for content in update_service:ss.test_remote(content)if op == 'stop':for content in update_service:ss.stop_prcee(content)if op == 'start':for content in update_service:if 'pro1' in ob or 'pro2' in ob:print "权限更新"ss.chown_set(content)ss.start_prcee(content)if op == 'ps':for content in update_service:ss.ps_prcee(content)if op == 'scp':for content in update_service:if ss.get_md5(content) != 0:l.debug('开始拷贝文件')ss.back_file(content)ss.get_file(content)print "更新完成MD5文件校验"ss.get_md5(content)#if 'pro' in ob:# print "权限更新"# ss.chown_set(content)else:l.debug('无需更新文件')if op == 'md5':for content in update_service:ss.get_md5(content)#检测输入,def main():pack_info()ACTIONS = ['test','stop','start','ps','scp','md5']webname = set(Service_Names)webname = list(webname)webname.sort()GROUPS = set(GROUPS_Names)parser = ArgumentParser()try:parser.add_argument('-v','--verbose',action='store_true',help='detail output')parser.add_argument('operation',choices=ACTIONS,help='action name')parser.add_argument('-o','--object',nargs=1,choices=GROUPS,help='object name')parser.add_argument('-w','--webname',nargs="+",choices=webname,help='update servername')except:print '%r'%tb.format_exc()args = parser.parse_args()handle(args)output_result()if __name__ == '__main__':main()