千家信息网

如何用paramiko模块写发版机

发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,本文小编为大家详细介绍"如何用paramiko模块写发版机",内容详细,步骤清晰,细节处理妥当,希望这篇"如何用paramiko模块写发版机"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来
千家信息网最后更新 2025年01月16日如何用paramiko模块写发版机

本文小编为大家详细介绍"如何用paramiko模块写发版机",内容详细,步骤清晰,细节处理妥当,希望这篇"如何用paramiko模块写发版机"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

说明:为了安全,本文敏感信息如ip、用户名密码等做了转换处理。

一、场景:每次发版时,都需要发版人一个一个文件的往生产机上拷贝,这样不仅费时,而且容易出错,降低工程师的工作积极性。

二、解决方法:需用python脚本写一个发版机,自动发版。

三、脚本实现的功能:自动合并develop_svn(开发svn)代码到online_svn(生产svn)下,自动备份远程服务器代码,手工通过ecplice编译online_svn代码,然后自动把编译后的class文件根据filelist里面的路径拷贝到生产机,并自动重启服务器上的tomcat服务。

四、具体步骤:

1、开发提供类似如下svn文件列表:

filelist.txt里面的内容:

/trunk/src/ha/lalala/controller/BoardController.java

/trunk/src/ha/lalala/pda/PdaWaybillController.java

/trunk/WebRoot/jsp/productReview/list.jsp

2、建立develop_svn和online_svn目录;

3、编写faban.py脚本

点击(此处)折叠或打开

  1. #-*-coding:utf-8-*-

  2. import Crypto #paramiko模块依赖Crypto模块

  3. import paramiko #paramiko模块是wnidows 远程linux机器用的模块

  4. import os

  5. import sys

  6. import shutil #shutil模块下有copy文件夹的方法

  7. import time #这里使用其休眠函数sleep

  8. import subprocess

  9. import glob




  10. #Update SVN

  11. def UpdateSVN(path):

  12. p = subprocess.Popen(['svn','update',path],shell=True,stdout=subprocess.PIPE)

  13. print p.stdout.readlines()




  14. #定义函数用来合并svn

  15. def MergeSVN(develop_svn,online_svn):

  16. with open('filelist.txt') as f:

  17. for index,line in enumerate(f,1): #1表示索引值从1开始

  18. line = line.replace('/trunk','') #替换路径

  19. line = line.replace('\n','') #把换行替换掉,\n是换行符的意思

  20. develop_svn_path=develop_svn + line #拼接路径

  21. online_svn_path = online_svn + line #拼接路径

  22. print "%d copying: %s ---> %s" % (index,develop_svn_path,online_svn_path)

  23. if not os.path.exists(os.path.dirname(online_svn_path)) : #如果目录不存在,就建立一个目录,注意exists方法返回的是布尔值,所以用Not进行否定

  24. os.mkdir(os.path.dirname(online_svn_path)) #建立目录

  25. shutil.copy(develop_svn_path,online_svn_path) #将develop_svn_path里面的代码拷贝到online_svn_path目录下

  26. print('\n') #输出一个换行

  27. print("合并SVN目录已完成,请手工通过ecplice编译代码".decode('utf-8').encode('gb2312'))

  28. print('\n') #输出一个换行





  29. #定义函数用来远程备份代码--给北京的机器备份

  30. def BackupCode(hostname,port,username,password):

  31. ssh = paramiko.SSHClient() #创建一个从客户端连接服务器端的对象,也就是类的实例化

  32. ssh.load_system_host_keys() #加载主机秘钥

  33. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #接受不在本地Known_host文件下的主机。否则ssh需要手工输入一次yes

  34. ssh.connect(hostname,port,username,password) #ssh连接


  35. stdin,stdout,stderr = ssh.exec_command(get_pty=False,command='dir=$(date +%Y%m%d%H%M%S) && \

  36. rsync -zrtopg --exclude geadPortrait/ \

  37. --exclude=idcard/ --exclude=temp/ --exclude=upload \

  38. --exclude=files --exclude=temporary_zip/ \

  39. /opt/apache-tomcat-8.0.27/webapps/ROOT /backup/tms/$dir') #执行远程机器的rsync命令进行备份,rsync命令没加-v参数,所以正常信息不会输出,只有报错才输出内容

  40. result = stdout.read() #内容输出

  41. error = stderr.read() #错误输出

  42. print result

  43. print error

  44. #判断是否有错误输出,没有就说备份成功,否则说备份失败

  45. if result.strip()=="" and error.strip()=="":

  46. print "%s 完美,备份成功,备份位置在远程机器的/backup目录下".decode('utf-8').encode('gb2312') % hostname

  47. print('\n')

  48. else:

  49. print "%s 不好了,备份失败了".decode('utf-8').encode('gb2312') % hostname

  50. print('\n')

  51. ssh.close() #记得关闭paramiko的ssh连接







  52. #定义函数用来远程备份代码--给香港腾讯的机器备份

  53. def BackupCode_HK_QQ(hostname,port,username,password):

  54. ssh = paramiko.SSHClient() #创建一个从客户端连接服务器端的对象,也就是类的实例化

  55. ssh.load_system_host_keys() #加载主机秘钥

  56. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #接受不在本地Known_host文件下的主机。否则ssh需要手工输入一次yes

  57. ssh.connect(hostname,port,username,password) #ssh连接

  58. stdin,stdout,stderr = ssh.exec_command(get_pty=False,command='dir=$(date +%Y%m%d%H%M%S) && \

  59. rsync -zrtopg --exclude geadPortrait/ \

  60. --exclude=idcard/ --exclude=temp/ --exclude=upload \

  61. --exclude=files --exclude=temporary_zip/ \

  62. /opt/tomcat-9090-tms/webapps/ROOT /backup/tms/$dir') #执行远程机器的rsync命令进行备份,rsync命令没加-v参数,所以正常信息不会输出,只有报错才输出内容

  63. result = stdout.read() #内容输出

  64. error = stderr.read() #错误输出

  65. print result

  66. print error

  67. #判断是否有错误输出,没有就说备份成功,否则说备份失败

  68. if result.strip()=="" and error.strip()=="":

  69. print "%s 完美,备份成功,备份位置在远程机器的/backup目录下".decode('utf-8').encode('gb2312') % hostname

  70. print('\n')

  71. else:

  72. print "%s 不好了,备份失败了".decode('utf-8').encode('gb2312') % hostname

  73. print('\n')

  74. ssh.close() #记得关闭paramiko的ssh连接





  75. #定义函数用来远程执行发版动作

  76. def Publish(hostname,port,username,password,local_base_path,remote_base_path):

  77. count = 0

  78. trans = paramiko.Transport(hostname,port) #建立paramiko的transport方式连接

  79. trans.connect(username=username,password=password) #建立连接

  80. sftp = paramiko.SFTPClient.from_transport(trans) #建立连接

  81. with open('filelist.txt','r') as f:

  82. for line in f:

  83. #本地路径预处理

  84. localpath_filename = line.replace('/trunk/src','WebRoot/WEB-INF/classes')

  85. localpath_filename = localpath_filename.replace('/trunk/WebRoot','WebRoot')

  86. localpath_filename = localpath_filename.replace('.java','.class')

  87. localpath_filename = localpath_filename.replace('\n','') #把换行替换掉

  88. #构造真正的父类本地路径

  89. localpath_filename = local_base_path + localpath_filename

  90. #构造真正的父类远程路径

  91. remotepath_filename = remote_base_path + localpath_filename.replace('online_svn/WebRoot/','')

  92. #拷贝父类到远程机器上

  93. print "%s is publishing: %s ---> %s " % (hostname,localpath_filename,remotepath_filename)

  94. try:

  95. sftp.listdir(os.path.dirname(remotepath_filename)) #加个错误处理,如果目录不存在,就建立一个目录

  96. except IOError:

  97. sftp.mkdir(os.path.dirname(remotepath_filename))

  98. sftp.put(localpath_filename,remotepath_filename)

  99. count += 1

  100. print "***********第%s个文件发版成功***************" % count

  101. #用glob模块寻找子类

  102. path_filename = os.path.split(localpath_filename) #split:返回一个二元组,包含文件的路径与文件名

  103. filename_splitext = os.path.splitext(path_filename[1]) #去掉文件扩展名

  104. localpath_subclassfilenames = glob.glob('%s/%s$*' % (path_filename[0],filename_splitext[0]))

  105. #把子类拷贝到远程机器的目录下

  106. for localpath_subclassfilename in localpath_subclassfilenames:

  107. localpath_subclassfilename = localpath_subclassfilename.replace('\\',r'/')

  108. remotepath_subclassfilename = remote_base_path + localpath_subclassfilename.replace('online_svn/WebRoot/','')

  109. print "%s is publishing: %s ---> %s " % (hostname,localpath_subclassfilename,remotepath_subclassfilename)

  110. sftp.put(localpath_subclassfilename,remotepath_subclassfilename)

  111. count += 1

  112. print "***********第%s个文件拷贝成功,注意该文件是子类哦^_^ *****************************************" % count

  113. print " %s机器发版完成!!!".decode('utf-8').encode('gb2312') % hostname

  114. print('\n')

  115. trans.close() #记得关闭paramiko的transport连接




  116. #定义函数用来重启服务

  117. def RestartService(hostname,port,username,password):

  118. ssh = paramiko.SSHClient() #创建一个从客户端连接服务器端的对象,也就是类的实例化

  119. ssh.load_system_host_keys() #加载主机秘钥

  120. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #接受不在本地Known_host文件下的主机。否则ssh需要手工输入一次yes

  121. ssh.connect(hostname,port,username,password) #ssh连接

  122. stdin,stdout,stderr = ssh.exec_command(get_pty=False,command='/usr/local/shell/restartservice.sh')

  123. result = stdout.read() #内容输出

  124. error = stderr.read() #错误输出

  125. print "%s 在重启服务...".decode('utf-8').encode('gb2312') % hostname

  126. print result

  127. print error

  128. print('\n')

  129. ssh.close() #记得关闭paramiko的ssh连接




  130. #主程序

  131. if __name__ == '__main__':

  132. #Update SVN

  133. while True:

  134. temp = str(raw_input('1) 请问你要Update SVN吗?[yes/no]:'.decode('utf-8').encode('gb2312')))

  135. tips = temp.strip().lower()

  136. if tips == 'yes':

  137. print "Now begin Update SVN..."

  138. UpdateSVN('develop_svn')

  139. break

  140. elif tips == 'no':

  141. break


  142. #合并svn

  143. while True:

  144. temp = str(raw_input('2) 请问你要把开发svn合并到生产svn里面吗?[yes/no]:'.decode('utf-8').encode('gb2312')))

  145. tips = temp.strip().lower()

  146. if tips == 'yes':

  147. print "Now begin Merge SVN..."

  148. MergeSVN('develop_svn','online_svn')

  149. break

  150. elif tips == 'no':

  151. break


  152. #备份远程机器上的代码

  153. while True:

  154. temp = str(raw_input('3)请问你要在发版前,备份一下远程服务器上的代码吗?[yes/no]:'.decode('utf-8').encode('gb2312')))

  155. tips = temp.strip().lower()

  156. if tips == 'yes':

  157. print "Now begin backup code..."

  158. BackupCode(hostname = '10.2.88.2',port = '22',username = 'tms',password = 'xxx')

  159. BackupCode(hostname = '10.2.88.3',port = '22',username = 'tms',password = 'xxx')

  160. BackupCode(hostname = '10.2.88.13',port = '22',username = 'tms',password = 'xxx')

  161. BackupCode(hostname = '10.2.88.14',port = '22',username = 'tms',password = 'xxx')

  162. BackupCode_HK_QQ(hostname = '10.144.89.252',port = '22',username = 'tms',password = 'xxx')

  163. break

  164. elif tips == 'no':

  165. break

  166. #提示是否eclipse编译代码

  167. while True:

  168. temp = str(raw_input('4) 提示:请问你手工通过eclse编译tms代码了吗[yes/no]:'))

  169. tips = temp.strip().lower()

  170. if tips == 'yes':

  171. break

  172. elif tips == 'no':

  173. break


  174. #预发版

  175. while True:

  176. temp = str(raw_input('5)请问你需要先单独在预发版机器10.2.88.3上测试一下子发版吗?[yes/no]:'.decode('utf-8').encode('gb2312')))

  177. tips = temp.strip().lower()

  178. if tips == 'yes':

  179. print "Now begin publish code..."

  180. Publish(hostname='10.2.88.3',port='22',username='tms',password='tmsOo798',local_base_path='online_svn/',remote_base_path='/opt/apache-tomcat-8.0.27/webapps/ROOT/')

  181. print "Now begin restart service..."

  182. RestartService(hostname = '10.2.88.3',port = '22',username = 'tms',password = 'tmsOo798')

  183. break

  184. elif tips == 'no':

  185. break


  186. #生产全发版

  187. while True:

  188. temp = str(raw_input('6)请问你要开始在所有正式服务器上进行发版吗,包括10.2.88.13/14/2/3,10.144.89.252?[yes/no]:'.decode('utf-8').encode('gb2312')))

  189. tips = temp.strip().lower()

  190. if tips == 'yes':

  191. print "Now begin publish code..."

  192. Publish(hostname='10.2.88.13',port='22',username='tms',password='xxx',local_base_path='online_svn/',remote_base_path='/opt/apache-tomcat-8.0.27/webapps/ROOT/')

  193. Publish(hostname='10.2.88.14',port='22',username='tms',password='xxx',local_base_path='online_svn/',remote_base_path='/opt/apache-tomcat-8.0.27/webapps/ROOT/')

  194. Publish(hostname='10.2.88.2',port='22',username='tms',password='xxx',local_base_path='online_svn/',remote_base_path='/opt/apache-tomcat-8.0.27/webapps/ROOT/')

  195. Publish(hostname='10.2.88.3',port='22',username='tms',password='xxx',local_base_path='online_svn/',remote_base_path='/opt/apache-tomcat-8.0.27/webapps/ROOT/')

  196. Publish(hostname='10.144.89.252',port='22',username='tms',password='xxx',local_base_path='online_svn/',remote_base_path='/opt/tomcat-9090-tms/webapps/ROOT/')


  197. break

  198. elif tips == 'no':

  199. break



  200. #重启服务

  201. while True:

  202. temp = str(raw_input('7)请问你要开始在所有正式服务器上重启服务吗,包括10.2.88.13/14/2/3,10.144.89.252?[yes/no]:'.decode('utf-8').encode('gb2312')))

  203. tips = temp.strip().lower()

  204. if tips == 'yes':

  205. print "Now begin restart service..."

  206. RestartService(hostname = '10.2.88.13',port = '22',username = 'tms',password = 'xxx')

  207. print "please wait 60s..."

  208. time.sleep(60)

  209. RestartService(hostname = '10.2.88.14',port = '22',username = 'tms',password = 'xxx')

  210. print "please wait 60s..."

  211. time.sleep(60)

  212. RestartService(hostname = '10.2.88.2',port = '22',username = 'tms',password = 'xxx')

  213. print "please wait 60s..."

  214. time.sleep(60)

  215. RestartService(hostname = '10.2.88.3',port = '22',username = 'tms',password = 'xxx')

  216. print "please wait 60s..."

  217. time.sleep(60)

  218. RestartService(hostname = '10.144.89.252',port = '22',username = 'tms',password = 'xxx')

  219. break

  220. elif tips == 'no':

  221. break


  222. #提示是否手工提交online_svn代码

  223. while True:

  224. temp = str(raw_input('8) 提示:请问你手工提交online_svn代码了吗?[yes/no]:'))

  225. tips = temp.strip().lower()

  226. if tips == 'yes':

  227. break

  228. elif tips == 'no':

  229. break


  230. #退出本程时要说的话

  231. print "\n"

  232. print "*" * 50

  233. print "亲,您的完版完成,记得测试业务是否正常哦!!!"

  234. print "*" * 50

  235. sys.exit()


  236. #加入下面这句话,才能用windows双击运行python脚本,否则双击脚本会一闪而过

  237. raw_input()

读到这里,这篇"如何用paramiko模块写发版机"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。

0