1. 程式人生 > 實用技巧 >微服務釋出指令碼

微服務釋出指令碼

  1. #!/usr/bin/python2.7
  2. #coding=utf-8
  3. '''
  4. Created on Oct 19
  5. @author [email protected] Update Version TO Wan
  6. Version 1.1
  7. '''
  8. import os
  9. import time
  10. import MySQLdb
  11. import json
  12. import logging
  13. import paramiko
  14. import traceback as tb
  15. from argparse import ArgumentParser
  16. l = logging.getLogger('online')
  17. #獲取時間用於打包備份命名
  18. D_TIME = time.strftime('%Y%m%d%H%M')
  19. #作為結果輸出
  20. logs = []
  21. #獲取腳本當前目錄
  22. cfd = os.path.dirname(os.path.abspath(__file__))
  23. SystemUpdatePath="/data/BusinesstoCustomer/program/"
  24. update_service = []
  25. Service_Names = []
  26. GROUPS_Names = []
  27. result=[]
  28. MYSQLHOST='127.0.0.1'
  29. MYSQLUSER='root'
  30. MYSQLPASSWD='Feng!1900'
  31. Version_Url='http://192.168.200.141:8557/program/'
  32. def Server_sql():
  33. conn = MySQLdb.connect(host=MYSQLHOST,user=MYSQLUSER,passwd=MYSQLPASSWD,db='ccdb')
  34. curs = conn.cursor()
  35. try:
  36. 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;''')
  37. conn.commit()
  38. data = curs.fetchall()
  39. #print u'fetchall()返回的資料:',data
  40. conn.close()
  41. jsonData = []
  42. for row in data:
  43. result = {}
  44. result['servername'] = str(row[0])
  45. result['SD_path'] = str(row[1])
  46. result['serverhosts'] = row[2]
  47. result['SI_path'] = str(row[3])
  48. result['Jenkins_name'] = str(row[4])
  49. result['SL_status'] = str(row[5])
  50. result['Ssystem_class'] = str(row[6])
  51. result['muser'] = str(row[7])
  52. result['mpass'] = str(row[8])
  53. result['rpass'] = str(row[9])
  54. result['wuser'] = str(row[10])
  55. result['muserkey'] = str(row[11])
  56. jsonData.append(result)
  57. #l.debug('轉換為列表字典的原始資料 : %r',jsonData)
  58. return json.dumps(jsonData)
  59. except:
  60. print 'MySQL connect fail...'
  61. else:
  62. #使用json.dumps將資料轉換為json格式,json.dumps方法預設會輸出成這種格式"\u5377\u76ae\u6298\u6263",加ensure_ascii=False,則能夠防止中文亂碼。
  63. #JSON採用完全獨立於語言的文字格式,事實上大部分現代計算機語言都以某種形式支援它們。這使得一種資料格式在同樣基於這些結構的程式語言之間交換成為可能。
  64. #json.dumps()是將原始資料轉為json(其中單引號會變為雙引號),而json.loads()是將json轉為原始資料。
  65. jsondatar=json.dumps(jsonData,ensure_ascii=False,sort_keys=True)
  66. #去除首尾的中括號
  67. return jsondatar[1:len(jsondatar)-1]
  68. def pack(ob,webnames):
  69. #取出相關伺服器資訊和狀態
  70. file_data=json.loads(Server_sql())
  71. for wname in webnames:
  72. for aa in file_data:
  73. for obi in ob:
  74. if aa['servername'] == wname and aa['Ssystem_class'] == obi:
  75. service_object = services(aa['servername'],aa['SD_path'],aa['serverhosts'],aa['SI_path'],aa['Jenkins_name'],
  76. aa['SL_status'],aa['Ssystem_class'],aa['muser'],aa['mpass'],aa['rpass'],aa['wuser'],aa['muserkey'])
  77. update_service.append(service_object)
  78. def pack_info():
  79. #取出相關伺服器資訊和狀態
  80. file_data=json.loads(Server_sql())
  81. for aa in file_data:
  82. service_name = aa['servername']
  83. groups_name = aa['Ssystem_class']
  84. Service_Names.append(service_name)
  85. Service_Names.append('all')
  86. GROUPS_Names.append(str(groups_name))
  87. GROUPS_Names.append('all')
  88. def scall(CMD_LINE):
  89. '''linux shell '''
  90. l.debug('CMD_LINE : %r',CMD_LINE)
  91. return call(CMD_LINE,shell=True)
  92. def os_system(cmd):
  93. result = os.popen(cmd)
  94. res = result.read()
  95. #for line in res.splitlines():
  96. #print line
  97. return res.splitlines()
  98. #封裝的自定義列印模組
  99. def head_print():
  100. print '\033[1;31;40m'
  101. #print '*' * 50
  102. #print '\n'
  103. #封裝的自定義列印模組
  104. def tail_print():
  105. #print '\n'
  106. #print '*' * 50
  107. print '\033[0m'
  108. #輸出操作結果
  109. def output_result():
  110. head_print()
  111. for count in range(len(logs)):
  112. print "\n"
  113. for content in logs[count]:
  114. if 'MD5校驗成功!' in content:
  115. print content
  116. break
  117. print content
  118. tail_print()
  119. class services:
  120. def __init__(self,servername,SD_path,serverhosts,SI_path,Jenkins_name,SL_status,Ssystem_class,muser,mpass,rpass,wuser,muserkey):
  121. self.servername = servername
  122. self.SD_path = SD_path
  123. self.SI_path = SI_path
  124. self.serverhosts = serverhosts
  125. self.Jenkins_name = Jenkins_name
  126. self.SL_status = SL_status
  127. self.Ssystem_class = Ssystem_class
  128. self.muser = muser
  129. self.mpass = mpass
  130. self.rpass = rpass
  131. self.wuser = wuser
  132. self.muserkey = muserkey
  133. self.LOG_PATH = '/data/logs'
  134. self.SPRINT_PATH = '/tmp/'
  135. def connect(self,cmd):
  136. s=paramiko.SSHClient()
  137. s.load_system_host_keys()
  138. s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  139. if 'pro' in self.Ssystem_class:
  140. pkey = paramiko.RSAKey.from_private_key_file(self.muserkey)
  141. s.connect(hostname=self.serverhosts,port=22,username=self.muser,pkey=pkey,allow_agent=False)
  142. else:
  143. s.connect(hostname=self.serverhosts,port=22,username=self.muser, password=self.mpass,allow_agent=False,look_for_keys=False)
  144. if self.muser != 'root':
  145. ssh = s.invoke_shell()
  146. time.sleep(0.1)
  147. ssh.send('su - \n')
  148. buff = ''
  149. while not buff.endswith('Password: '):
  150. resp = ssh.recv(9999)
  151. buff +=resp
  152. ssh.send(self.rpass)
  153. ssh.send('\n')
  154. buff = ''
  155. while not buff.endswith('# '):
  156. resp = ssh.recv(9999)
  157. buff +=resp
  158. ssh.send(cmd)
  159. ssh.send('\n')
  160. buff = ''
  161. while not buff.endswith('# '):
  162. resp = ssh.recv(9999)
  163. buff +=resp
  164. s.close()
  165. result = buff
  166. else:
  167. stdin, stdout, stderr = s.exec_command(cmd)
  168. result = stdout.read()
  169. s.close()
  170. l.debug('result %r',result)
  171. print self.serverhosts, cmd
  172. return result
  173. #關閉遠端伺服器tomcat
  174. def test_remote(self):
  175. #關閉遠端程序
  176. shl='''ifconfig eth0|grep inet'''
  177. l.debug('%r',shl)
  178. self.connect(cmd=shl)
  179. def stop_prcee(self):
  180. shl='''pkill -f %(name)s'''%{'name':self.servername}
  181. shl2='''ps aux|grep %(name)s|grep -v grep'''%{'name':self.servername}
  182. l.debug('%r',shl)
  183. l.debug('%r',shl2)
  184. self.connect(cmd=shl)
  185. self.connect(cmd=shl2)
  186. def start_prcee(self):
  187. '''su - user -c'''
  188. if self.wuser == 'root':
  189. shl='''/usr/bin/sh -l %(path)s/bin/start.sh '''%{'path':self.SI_path}
  190. else:
  191. shl='''runuser -l %(user)s -c "/usr/bin/sh -l %(path)s/bin/start.sh" '''%{'path':self.SI_path,'user':self.wuser}
  192. #shl='''su -c %(user)s "/usr/bin/sh -l %(path)s/bin/start.sh" '''%{'path':self.SI_path,'user':self.wuser}
  193. shl2='''ps aux|grep %(name)s|grep -v grep'''%{'name':self.servername}
  194. l.debug('%r',shl)
  195. l.debug('%r',shl2)
  196. self.connect(cmd=shl)
  197. self.connect(cmd=shl2)
  198. def ps_prcee(self):
  199. shl='''ps aux|grep %(name)s|grep -v grep'''%{'name':self.servername}
  200. l.debug('%r',shl)
  201. self.connect(cmd=shl)
  202. def chown_set(self):
  203. sh3 = '''chown -R %s %s''' %(self.wuser,self.SPRINT_PATH)
  204. sh1 = '''chown -R %s %s''' %(self.wuser,self.SI_path)
  205. sh2 = '''chown -R %s %s''' %(self.wuser,self.LOG_PATH)
  206. self.connect(cmd=sh3)
  207. self.connect(cmd=sh2)
  208. self.connect(cmd=sh1)
  209. def get_file(self):
  210. shl='''wget -NP %s %s'''%(self.SI_path+'/lib/',Version_Url+self.servername+'/'+self.Jenkins_name)
  211. l.debug('%r',shl)
  212. self.connect(cmd=shl)
  213. def get_md5(self):
  214. shl1='''/usr/bin/md5sum %s |cut -d ' ' -f1'''%(self.SD_path +'/' +self.Jenkins_name)
  215. local_md5 = os_system(shl1)[0]
  216. l.debug('local_md5 %r',local_md5)
  217. shl='''/usr/bin/md5sum %s |cut -d ' ' -f1'''%(self.SI_path +'/lib/'+self.Jenkins_name)
  218. remote_md5 = self.connect(cmd=shl).split()[8]
  219. l.debug('remote_md5 %r',remote_md5)
  220. print self.Jenkins_name
  221. print "本地檔案MD5",local_md5
  222. print "遠端檔案MD5",remote_md5
  223. return cmp(local_md5,remote_md5)
  224. def back_file(self):
  225. shl1="if [ ! -d %s/lib/backup/ ];then mkdir %s/lib/backup/;fi" %(self.SI_path,self.SI_path)
  226. shl='''scp %s %s'''%(self.SI_path +'/lib/'+self.Jenkins_name,self.SI_path +'/lib/backup/'+self.Jenkins_name+'_%s'%D_TIME)
  227. l.debug('%r',shl)
  228. self.connect(cmd=shl1)
  229. self.connect(cmd=shl)
  230. #檢測引數,執行操作
  231. def handle(args):
  232. logging.basicConfig(format="%(message)s")
  233. l.level = logging.INFO
  234. if args.verbose:
  235. l.level =logging.DEBUG
  236. op = args.operation
  237. ob = args.object
  238. webnames = args.webname
  239. ss = services
  240. if 'all' in webnames:
  241. pack_info()
  242. Service_Names.remove('all')
  243. webname = set(Service_Names)
  244. pack(ob,webname)
  245. else:
  246. pack(ob,webnames)
  247. if not op:
  248. '''利用列表的方式實現swith功能'''
  249. comlist = ['stop','scp','ps','start',]
  250. else:
  251. comlist = [op]
  252. if op == 'test':
  253. for content in update_service:
  254. ss.test_remote(content)
  255. if op == 'stop':
  256. for content in update_service:
  257. ss.stop_prcee(content)
  258. if op == 'start':
  259. for content in update_service:
  260. if 'pro1' in ob or 'pro2' in ob:
  261. print "許可權更新"
  262. ss.chown_set(content)
  263. ss.start_prcee(content)
  264. if op == 'ps':
  265. for content in update_service:
  266. ss.ps_prcee(content)
  267. if op == 'scp':
  268. for content in update_service:
  269. if ss.get_md5(content) != 0:
  270. l.debug('開始拷貝檔案')
  271. ss.back_file(content)
  272. ss.get_file(content)
  273. print "更新完成MD5檔案校驗"
  274. ss.get_md5(content)
  275. #if 'pro' in ob:
  276. # print "許可權更新"
  277. # ss.chown_set(content)
  278. else:
  279. l.debug('無需更新檔案')
  280. if op == 'md5':
  281. for content in update_service:
  282. ss.get_md5(content)
  283. #檢測輸入,
  284. def main():
  285. pack_info()
  286. ACTIONS = ['test','stop','start','ps','scp','md5']
  287. webname = set(Service_Names)
  288. webname = list(webname)
  289. webname.sort()
  290. GROUPS = set(GROUPS_Names)
  291. parser = ArgumentParser()
  292. try:
  293. parser.add_argument('-v','--verbose',action='store_true',help='detail output')
  294. parser.add_argument('operation',choices=ACTIONS,help='action name')
  295. parser.add_argument('-o','--object',nargs=1,choices=GROUPS,help='object name')
  296. parser.add_argument('-w','--webname',nargs="+",choices=webname,help='update servername')
  297. except:
  298. print '%r'%tb.format_exc()
  299. args = parser.parse_args()
  300. handle(args)
  301. output_result()
  302. if __name__ == '__main__':
  303. main()