用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指令碼
3、編寫faban.py指令碼
點選(此處)摺疊或開啟
-
#-*-coding:utf-8-*-
-
import Crypto #paramiko模組依賴Crypto模組
-
import paramiko #paramiko模組是wnidows 遠端linux機器用的模組
-
import os
-
import sys
-
import shutil #shutil模組下有copy資料夾的方法
-
import time #這裡使用其休眠函式sleep
-
import subprocess
-
import glob
-
-
-
-
#Update SVN
-
def UpdateSVN(path):
-
p = subprocess.Popen(['svn','update',path],shell=True,stdout=subprocess.PIPE)
-
print p.stdout.readlines()
-
-
-
-
#定義函式用來合併svn
-
def MergeSVN(develop_svn,online_svn):
-
with open('filelist.txt') as f:
-
for index,line in enumerate(f,1): #1表示索引值從1開始
-
line = line.replace('/trunk','') #替換路徑
-
line = line.replace('\n','') #把換行替換掉,\n是換行符的意思
-
develop_svn_path=develop_svn + line #拼接路徑
-
online_svn_path = online_svn + line #拼接路徑
-
print "%d copying: %s ---> %s" % (index,develop_svn_path,online_svn_path)
-
if not os.path.exists(os.path.dirname(online_svn_path)) : #如果目錄不存在,就建立一個目錄,注意exists方法返回的是布林值,所以用Not進行否定
-
os.mkdir(os.path.dirname(online_svn_path)) #建立目錄
-
shutil.copy(develop_svn_path,online_svn_path) #將develop_svn_path裡面的程式碼複製到online_svn_path目錄下
-
print('\n') #輸出一個換行
-
print("合併SVN目錄已完成,請手工透過ecplice編譯程式碼".decode('utf-8').encode('gb2312'))
-
print('\n') #輸出一個換行
-
-
-
-
-
#定義函式用來遠端備份程式碼--給北京的機器備份
-
def BackupCode(hostname,port,username,password):
-
ssh = paramiko.SSHClient() #建立一個從客戶端連線伺服器端的物件,也就是類的例項化
-
ssh.load_system_host_keys() #載入主機秘鑰
-
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #接受不在本地Known_host檔案下的主機。否則ssh需要手工輸入一次yes
-
ssh.connect(hostname,port,username,password) #ssh連線
-
-
stdin,stdout,stderr = ssh.exec_command(get_pty=False,command='dir=$(date +%Y%m%d%H%M%S) && \
-
rsync -zrtopg --exclude geadPortrait/ \
-
--exclude=idcard/ --exclude=temp/ --exclude=upload \
-
--exclude=files --exclude=temporary_zip/ \
-
/opt/apache-tomcat-8.0.27/webapps/ROOT /backup/tms/$dir') #執行遠端機器的rsync命令進行備份,rsync命令沒加-v引數,所以正常資訊不會輸出,只有報錯才輸出內容
-
result = stdout.read() #內容輸出
-
error = stderr.read() #錯誤輸出
-
print result
-
print error
-
#判斷是否有錯誤輸出,沒有就說備份成功,否則說備份失敗
-
if result.strip()=="" and error.strip()=="":
-
print "%s 完美,備份成功,備份位置在遠端機器的/backup目錄下".decode('utf-8').encode('gb2312') % hostname
-
print('\n')
-
else:
-
print "%s 不好了,備份失敗了".decode('utf-8').encode('gb2312') % hostname
-
print('\n')
-
ssh.close() #記得關閉paramiko的ssh連線
-
-
-
-
-
-
-
#定義函式用來遠端備份程式碼--給香港騰訊的機器備份
-
def BackupCode_HK_QQ(hostname,port,username,password):
-
ssh = paramiko.SSHClient() #建立一個從客戶端連線伺服器端的物件,也就是類的例項化
-
ssh.load_system_host_keys() #載入主機秘鑰
-
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #接受不在本地Known_host檔案下的主機。否則ssh需要手工輸入一次yes
-
ssh.connect(hostname,port,username,password) #ssh連線
-
stdin,stdout,stderr = ssh.exec_command(get_pty=False,command='dir=$(date +%Y%m%d%H%M%S) && \
-
rsync -zrtopg --exclude geadPortrait/ \
-
--exclude=idcard/ --exclude=temp/ --exclude=upload \
-
--exclude=files --exclude=temporary_zip/ \
-
/opt/tomcat-9090-tms/webapps/ROOT /backup/tms/$dir') #執行遠端機器的rsync命令進行備份,rsync命令沒加-v引數,所以正常資訊不會輸出,只有報錯才輸出內容
-
result = stdout.read() #內容輸出
-
error = stderr.read() #錯誤輸出
-
print result
-
print error
-
#判斷是否有錯誤輸出,沒有就說備份成功,否則說備份失敗
-
if result.strip()=="" and error.strip()=="":
-
print "%s 完美,備份成功,備份位置在遠端機器的/backup目錄下".decode('utf-8').encode('gb2312') % hostname
-
print('\n')
-
else:
-
print "%s 不好了,備份失敗了".decode('utf-8').encode('gb2312') % hostname
-
print('\n')
-
ssh.close() #記得關閉paramiko的ssh連線
-
-
-
-
-
#定義函式用來遠端執行發版動作
-
def Publish(hostname,port,username,password,local_base_path,remote_base_path):
-
count = 0
-
trans = paramiko.Transport(hostname,port) #建立paramiko的transport方式連線
-
trans.connect(username=username,password=password) #建立連線
-
sftp = paramiko.SFTPClient.from_transport(trans) #建立連線
-
with open('filelist.txt','r') as f:
-
for line in f:
-
#本地路徑預處理
-
localpath_filename = line.replace('/trunk/src','WebRoot/WEB-INF/classes')
-
localpath_filename = localpath_filename.replace('/trunk/WebRoot','WebRoot')
-
localpath_filename = localpath_filename.replace('.java','.class')
-
localpath_filename = localpath_filename.replace('\n','') #把換行替換掉
-
#構造真正的父類本地路徑
-
localpath_filename = local_base_path + localpath_filename
-
#構造真正的父類遠端路徑
-
remotepath_filename = remote_base_path + localpath_filename.replace('online_svn/WebRoot/','')
-
#複製父類到遠端機器上
-
print "%s is publishing: %s ---> %s " % (hostname,localpath_filename,remotepath_filename)
-
try:
-
sftp.listdir(os.path.dirname(remotepath_filename)) #加個錯誤處理,如果目錄不存在,就建立一個目錄
-
except IOError:
-
sftp.mkdir(os.path.dirname(remotepath_filename))
-
sftp.put(localpath_filename,remotepath_filename)
-
count += 1
-
print "***********第%s個檔案發版成功***************" % count
-
#用glob模組尋找子類
-
path_filename = os.path.split(localpath_filename) #split:返回一個二元組,包含檔案的路徑與檔名
-
filename_splitext = os.path.splitext(path_filename[1]) #去掉副檔名
-
localpath_subclassfilenames = glob.glob('%s/%s$*' % (path_filename[0],filename_splitext[0]))
-
#把子類複製到遠端機器的目錄下
-
for localpath_subclassfilename in localpath_subclassfilenames:
-
localpath_subclassfilename = localpath_subclassfilename.replace('\\',r'/')
-
remotepath_subclassfilename = remote_base_path + localpath_subclassfilename.replace('online_svn/WebRoot/','')
-
print "%s is publishing: %s ---> %s " % (hostname,localpath_subclassfilename,remotepath_subclassfilename)
-
sftp.put(localpath_subclassfilename,remotepath_subclassfilename)
-
count += 1
-
print "***********第%s個檔案複製成功,注意該檔案是子類哦^_^ *****************************************" % count
-
print " %s機器發版完成!!!".decode('utf-8').encode('gb2312') % hostname
-
print('\n')
-
trans.close() #記得關閉paramiko的transport連線
-
-
-
-
#定義函式用來重啟服務
-
def RestartService(hostname,port,username,password):
-
ssh = paramiko.SSHClient() #建立一個從客戶端連線伺服器端的物件,也就是類的例項化
-
ssh.load_system_host_keys() #載入主機秘鑰
-
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #接受不在本地Known_host檔案下的主機。否則ssh需要手工輸入一次yes
-
ssh.connect(hostname,port,username,password) #ssh連線
-
stdin,stdout,stderr = ssh.exec_command(get_pty=False,command='/usr/local/shell/restartservice.sh')
-
result = stdout.read() #內容輸出
-
error = stderr.read() #錯誤輸出
-
print "%s 在重啟服務...".decode('utf-8').encode('gb2312') % hostname
-
print result
-
print error
-
print('\n')
-
ssh.close() #記得關閉paramiko的ssh連線
-
-
-
-
#主程式
-
if __name__ == '__main__':
-
#Update SVN
-
while True:
-
temp = str(raw_input('1) 請問你要Update SVN嗎?[yes/no]:'.decode('utf-8').encode('gb2312')))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
print "Now begin Update SVN..."
-
UpdateSVN('develop_svn')
-
break
-
elif tips == 'no':
-
break
-
-
#合併svn
-
while True:
-
temp = str(raw_input('2) 請問你要把開發svn合併到生產svn裡面嗎?[yes/no]:'.decode('utf-8').encode('gb2312')))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
print "Now begin Merge SVN..."
-
MergeSVN('develop_svn','online_svn')
-
break
-
elif tips == 'no':
-
break
-
-
#備份遠端機器上的程式碼
-
while True:
-
temp = str(raw_input('3)請問你要在發版前,備份一下遠端伺服器上的程式碼嗎?[yes/no]:'.decode('utf-8').encode('gb2312')))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
print "Now begin backup code..."
-
BackupCode(hostname = '10.2.88.2',port = '22',username = 'tms',password = 'xxx')
-
BackupCode(hostname = '10.2.88.3',port = '22',username = 'tms',password = 'xxx')
-
BackupCode(hostname = '10.2.88.13',port = '22',username = 'tms',password = 'xxx')
-
BackupCode(hostname = '10.2.88.14',port = '22',username = 'tms',password = 'xxx')
-
BackupCode_HK_QQ(hostname = '10.144.89.252',port = '22',username = 'tms',password = 'xxx')
-
break
-
elif tips == 'no':
-
break
-
#提示是否eclipse編譯程式碼
-
while True:
-
temp = str(raw_input('4) 提示:請問你手工透過eclse編譯tms程式碼了嗎[yes/no]:'))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
break
-
elif tips == 'no':
-
break
-
-
#預發版
-
while True:
-
temp = str(raw_input('5)請問你需要先單獨在預發版機器10.2.88.3上測試一下子發版嗎?[yes/no]:'.decode('utf-8').encode('gb2312')))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
print "Now begin publish code..."
-
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/')
-
print "Now begin restart service..."
-
RestartService(hostname = '10.2.88.3',port = '22',username = 'tms',password = 'tmsOo798')
-
break
-
elif tips == 'no':
-
break
-
-
#生產全發版
-
while True:
-
temp = str(raw_input('6)請問你要開始在所有正式伺服器上進行發版嗎,包括10.2.88.13/14/2/3,10.144.89.252?[yes/no]:'.decode('utf-8').encode('gb2312')))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
print "Now begin publish code..."
-
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/')
-
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/')
-
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/')
-
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/')
-
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/')
-
-
break
-
elif tips == 'no':
-
break
-
-
-
#重啟服務
-
while True:
-
temp = str(raw_input('7)請問你要開始在所有正式伺服器上重啟服務嗎,包括10.2.88.13/14/2/3,10.144.89.252?[yes/no]:'.decode('utf-8').encode('gb2312')))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
print "Now begin restart service..."
-
RestartService(hostname = '10.2.88.13',port = '22',username = 'tms',password = 'xxx')
-
print "please wait 60s..."
-
time.sleep(60)
-
RestartService(hostname = '10.2.88.14',port = '22',username = 'tms',password = 'xxx')
-
print "please wait 60s..."
-
time.sleep(60)
-
RestartService(hostname = '10.2.88.2',port = '22',username = 'tms',password = 'xxx')
-
print "please wait 60s..."
-
time.sleep(60)
-
RestartService(hostname = '10.2.88.3',port = '22',username = 'tms',password = 'xxx')
-
print "please wait 60s..."
-
time.sleep(60)
-
RestartService(hostname = '10.144.89.252',port = '22',username = 'tms',password = 'xxx')
-
break
-
elif tips == 'no':
-
break
-
-
#提示是否手工提交online_svn程式碼
-
while True:
-
temp = str(raw_input('8) 提示:請問你手工提交online_svn程式碼了嗎?[yes/no]:'))
-
tips = temp.strip().lower()
-
if tips == 'yes':
-
break
-
elif tips == 'no':
-
break
-
-
#退出本程時要說的話
-
print "\n"
-
print "*" * 50
-
print "親,您的完版完成,記得測試業務是否正常哦!!!"
-
print "*" * 50
-
sys.exit()
-
-
-
#加入下面這句話,才能用windows雙擊執行python指令碼,否則雙擊指令碼會一閃而過
- raw_input()
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28916011/viewspace-2153244/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python中paramiko 模組的用法Python
- Paramiko模組簡單使用
- python模組paramiko與sshPython
- python paramiko模組管理SSHPython
- Paramiko模組安裝與使用
- Python paramiko模組的安裝與使用Python
- 通過paramiko模組在遠端主機上執行命令
- python常用模組之paramiko與sshPython
- python3匯入paramiko模組Python
- 使用typescript開發angular模組(編寫模組)TypeScriptAngular
- python 3呼叫paramiko模組報錯AttributeError: modulePythonError
- 在Windows和Linux上安裝paramiko模組薦WindowsLinux
- 用樂高玩具發明寫賀卡的機器人機器人
- Python筆記之paramiko模組安裝和使用示例Python筆記
- python模組paramiko的上傳下載和遠端執行命令方法Python
- python paramiko模組中設定執行命令超時值薦Python
- python模組paramiko的上傳下載和遠端執行命令方法薦Python
- python paramikoPython
- 測試報告在發版前還是發版後寫測試報告
- JavaScript 模組化程式設計(一):模組的寫法JavaScript程式設計
- 使用paramiko遠端執行命令、下發檔案
- 基於paramiko的檔案批次分發和命令批次執行
- AMD、CMD、UMD 模組的寫法
- 深入Node.js的模組載入機制,手寫require函式Node.jsUI函式
- 編寫你自己的Python模組Python
- 寫害羞的程式碼才能模組化
- 編寫Node原生模組
- 在Unix下用C編寫curses程式的一些常用模組(轉)
- paramiko建立可互動的ssh會話會話
- drozer模組的編寫及模組動態載入問題研究
- Xposed模組的開發
- paramiko 2.4.1原始碼安裝原始碼
- Substrate 區塊鏈應用開發之存證模組的功能開發區塊鏈
- 模組機制
- 如何編寫型別安全的CSS模組型別CSS
- 你用過不寫程式碼就能完成一個簡單模組的元件麼?元件
- 好用的寫作軟體推薦:Scrivener mac中文啟用版Mac
- 如何編寫python模組Python