Jenkins持續集成-自動化部署腳本的實現《python》
讀者須知:
1、本手記本著記續接前面的兩張手記內容整理
2、本手記針對tomcat部署測試環境實現
最近工作比較繁忙,導致這章一直拖延,沒有太抽出時間來總結。要實現Jenkins端的持續集成,其實在CI服務配置端很容易,難點呢?就是如何實現自動化的部署。我的腳本設計就是為了解決以下難題:
難點一、如何使得自動化部署腳本更通用
我用的腳本,依賴依賴一個配置文件的模塊化,讓每一個應用業務模塊更加通用。自動化所執行的命令呢?
我也是設計想法本著更加通用平臺的原則,至少對於tomcat+java or java+socket這種模式通用。
難點二、如何使得自動化的部署簡單有效
本腳本,更加切合實際,例:自動化部署關閉tomcat,我們常常會選擇catalina.sh stop去關閉,然而這裏我選擇了kill的方式,如果檢測中沒有順利關閉,我將調用kill -9 去直接關閉。(沒辦法,選擇了通用,你是沒遇到過tomcat 一直有線程卡住,關閉不了的情況吧。)
難點三、需要讓我們自動化的部署實現高的可靠性
體現在:
1、每一次的部署,配置選項中都會進行備份。(備份只一次)
2、服務自動備份完畢後,需要實現檢測(這裏我在配置模塊中有加入日誌終端輸出)
當然,這個腳本中還有未完成的地方:
1、服務啟動後,自動化的檢測機制還是太薄弱。
2、暫時此腳本還無法通用到php,python等環境的更多平臺
3、代碼備份方式上,應該更加具更多靈活性。
這裏,如果你覺得我的腳本可以補充,不如大家一起加入進來(留言、或者郵件我[email protected]),我也很想學習學習大家的想法。
一、自動化部署原理圖示
1、2、3、4 表示執行的4個部署基礎步驟
圖片描述
二、實現
1、Tomcat 進程設置唯一標記
用於識別出一個服務器中唯一的Tomcat進程
java -Dmyapp.name=“project_name”
如果用的tomcat我們可以,直接修改啟動控制文件catalina.sh。
JAVA_OPTS="-Dmyapp.name:"project_name" -server -Xms1024M -Xmx4096M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=1024M"
2、實現自動化登錄
一般有兩種方式:
方式一、模擬用戶密碼交互方式,大家可以學習家py中依賴pexcept模塊。
方式二、用ssh + Key方式,這個是ssh的一種公鑰認證機制。本腳本中用的這種,大家自行學習。
3、CI服務器需要在服務端配置rsync服務端
實現中,主要用於客戶端服務拖取代碼。
4、配置文件解釋
[imoocc.com-server] //服務的模塊名稱,這裏需要註意,需要具有唯一性,且服務的進程標示命名一致
CI_IP=ci.iaskjob.com //CI服務器地址
Login_ISA_Key=/back/key/jeson_iaskjob_rsa //登錄ISA的key
Project_IP=192.168.10.99 //工程IP
Project_Login_User=root //對應工程機器登錄用戶
Project_Login_Port=22 //對應工程機器登錄端口
Project_Code_File=/tmp/imoocc //對應工程在CI服務器構建後的執行代碼目錄
Project_Exclude_File="/var/cache","/var/tmp","jdbc.profile" //不需要向線上同步的文件,如配置文件等等
Project_Backup_Dir=/opt/Jenkins_Backup_Dir //工程備份目錄
Project_Deploy_Path=/opt/imoocc //工程部署目錄
Project_Start_Command=tomcat/bin/catalina.sh start //工程啟動方式
Project_Log_Path=/tmp/imoocc.log //啟動後日誌的查看方式
分享代碼如下:
# -*- coding: utf-8 -*- #!/usr/bin/python ######################################################################### # File Name: Jenkins_Project_Deploy.py # Program function: ueed for deployment code in CI server. # Author:Jeson # mail:[email protected] # Created Time: 一 6/20 19:24:33 2016 #========================================================================import ConfigParser import sys from sys import argv import paramiko def Gennerate_cmd(Project_Name,CI_IP,Project_Code_File,Project_Exclude_File,Project_Backup_Dir,Project_Deploy_Path,Project_Start_Command,Project_Log_Path): cmd = [] #生成備份命令 if Project_Backup_Dir: #生成備份原有文件 cmd.append("mkdir -p /opt/") cmd.append("rsync -avzP %s %s && touch /tmp/CI_%s_backuptrue"%(Project_Deploy_Path,Project_Backup_Dir,Project_Name)) #生成關閉原有進程命令 cmd.append(‘test -e /tmp/CI_%s_backuptrue && ps -auxgrep "name:%s"grep -v grepawk \‘{print $2}\‘xargs kill‘%(Project_Name,Project_Name)) #生成命令-確認原來服務已經順利關閉 cmd.append(‘ps -auxgrep "name:%s"grep -v grepawk \‘{print $2}\‘&& touch /tmp/CI_killSucc ps -auxgrep "name:%s"grep -v grepawk \‘{print $2}\‘xargs kill -9‘%(Project_Name,Project_Name)) #生成命令-用於同步新的代碼文件 if Project_Code_File == "": cmd.append(‘test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s %s‘%(Project_Name,Project_Exclude_File,CI_IP,Project_Name,Project_Deploy_Path)) else: cmd.append(‘test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s/%s %s‘%(Project_Name,Project_Exclude_File,CI_IP,Project_Name,Project_Code_File,Project_Deploy_Path)) #生成命令-用於啟動服務 cmd.append(Project_Start_Command) #生成命令-查看服務啟動後的日誌 cmd.append(‘tail -n 200 -f %s‘%Project_Log_Path) #生成命令-清理此次生成的臨時文件 # cmd.append(‘rm -f /tmp/\*%s\*‘%Project_Name) return cmd def Login_Execute_Command(Project_IP,Project_Login_Port,Project_Login_User,Login_ISA_Key,cmds): Project_Port = int(Project_Login_Port) if Project_Login_Port else 22 if Project_IP and Project_Login_User and Login_ISA_Key: key = paramiko.RSAKey.from_private_key_file(Login_ISA_Key) s = paramiko.SSHClient() s.load_system_host_keys() s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) s.connect(hostname=Project_IP,port=Project_Port,username=Project_Login_User,pkey=key) for cmd_item in cmds: stdin,stdout,stderr=s.exec_command(cmd_item) print stdout.read() return True else: return false def main(): if len(argv) > 2: Config_File = argv[1] if argv[1] else "./Jenkins_Project_Deploy.conf " Project_Name = argv[2] if argv[2] else "" else: print "Error 0:Input argv format error! ./Jenkins_Project_Deploy.py ./test.conf testname" sys.exit() try: cf = ConfigParser.ConfigParser() cf.read(Config_File) CI_IP = cf.get(Project_Name, "CI_IP") Project_Code_File = cf.get(Project_Name, "Project_Code_File") Project_Exclude_File = cf.get(Project_Name, "Project_Exclude_File") Project_Backup_Dir = cf.get(Project_Name, "Project_Backup_Dir") Project_Deploy_Path = cf.get(Project_Name, "Project_Deploy_Path") Project_Start_Command = cf.get(Project_Name, "Project_Start_Command") Project_Log_Path = cf.get(Project_Name, "Project_Log_Path") execute_command = Gennerate_cmd(Project_Name,CI_IP,Project_Code_File,Project_Exclude_File,Project_Backup_Dir,Project_Deploy_Path,Project_Start_Command,Project_Log_Path) print "{Step 1: Command collected over!}",execute_command Project_IP = cf.get(Project_Name, "Project_IP") Project_Login_Port = cf.get(Project_Name, "Project_Login_Port") Project_Login_User = cf.get(Project_Name, "Project_Login_User") Login_ISA_Key = cf.get(Project_Name, "Login_ISA_Key") except Exception as e: print "Error 1: %s file open or read error!"%Config_File sys.exit() print "{Step 2:Prepare to loging...}",Project_IP result = Login_Execute_Command(Project_IP,Project_Login_Port,Project_Login_User,Login_ISA_Key,cmds=execute_command) if result is False: print "Error 3:Execute command failed!" if __name__ == ‘__main__‘: main()
慕課網
- 下載APP
- 購物車1
-
Jenkins持續集成-自動化部署腳本的實現 原創
2016-08-28 23:47:54 12643瀏覽 1評論 小字號幕客技術
Python工程師 關註公眾號"幕客技術" 35篇手記 4推薦作者的熱門手記
-
Jenkins-持續集成平臺(安裝篇)
15969瀏覽 60推薦 1評論 -
雲時代!我們該如何成為一個優秀的運維工程師
4432瀏覽 52推薦 4評論 -
日誌大了,怎麽辦?用我的日誌切割腳本吧!
10008瀏覽 51推薦 3評論 -
用Jenkins構建一個新工程,我們一起試一下!
11317瀏覽 36推薦 3評論 -
從小站到大站的部署架構總結
2347瀏覽 27推薦 0評論
讀者須知:
1、本手記本著記續接前面的兩張手記內容整理
2、本手記針對tomcat部署測試環境實現
最近工作比較繁忙,導致這章一直拖延,沒有太抽出時間來總結。要實現Jenkins端的持續集成,其實在CI服務配置端很容易,難點呢?就是如何實現自動化的部署。我的腳本設計就是為了解決以下難題:
難點一、如何使得自動化部署腳本更通用
我用的腳本,依賴依賴一個配置文件的模塊化,讓每一個應用業務模塊更加通用。自動化所執行的命令呢?
我也是設計想法本著更加通用平臺的原則,至少對於tomcat+java or java+socket這種模式通用。
難點二、如何使得自動化的部署簡單有效
本腳本,更加切合實際,例:自動化部署關閉tomcat,我們常常會選擇catalina.sh
stop去關閉,然而這裏我選擇了kill的方式,如果檢測中沒有順利關閉,我將調用kill -9
去直接關閉。(沒辦法,選擇了通用,你是沒遇到過tomcat 一直有線程卡住,關閉不了的情況吧。)
難點三、需要讓我們自動化的部署實現高的可靠性
體現在:
1、每一次的部署,配置選項中都會進行備份。(備份只一次)
2、服務自動備份完畢後,需要實現檢測(這裏我在配置模塊中有加入日誌終端輸出)
當然,這個腳本中還有未完成的地方:
1、服務啟動後,自動化的檢測機制還是太薄弱。
2、暫時此腳本還無法通用到php,python等環境的更多平臺
3、代碼備份方式上,應該更加具更多靈活性。
這裏,如果你覺得我的腳本可以補充,不如大家一起加入進來(留言、或者郵件我[email protected]),我也很想學習學習大家的想法。
一、自動化部署原理圖示
1、2、3、4 表示執行的4個部署基礎步驟
二、實現
- 1、Tomcat 進程設置唯一標記
用於識別出一個服務器中唯一的Tomcat進程
java -Dmyapp.name=“project_name”
如果用的tomcat我們可以,直接修改啟動控制文件catalina.sh。
JAVA_OPTS="-Dmyapp.name:"project_name" -server -Xms1024M -Xmx4096M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=1024M"
- 2、實現自動化登錄
一般有兩種方式:
方式一、模擬用戶密碼交互方式,大家可以學習家py中依賴pexcept模塊。
方式二、用ssh + Key方式,這個是ssh的一種公鑰認證機制。本腳本中用的這種,大家自行學習。
3、CI服務器需要在服務端配置rsync服務端
實現中,主要用於客戶端服務拖取代碼。
4、配置文件解釋
[imoocc.com-server] //服務的模塊名稱,這裏需要註意,需要具有唯一性,且服務的進程標示命名一致
CI_IP=ci.iaskjob.com //CI服務器地址
Login_ISA_Key=/back/key/jeson_iaskjob_rsa //登錄ISA的key
Project_IP=192.168.10.99 //工程IP
Project_Login_User=root //對應工程機器登錄用戶
Project_Login_Port=22 //對應工程機器登錄端口
Project_Code_File=/tmp/imoocc //對應工程在CI服務器構建後的執行代碼目錄
Project_Exclude_File="/var/cache","/var/tmp","jdbc.profile" //不需要向線上同步的文件,如配置文件等等
Project_Backup_Dir=/opt/Jenkins_Backup_Dir //工程備份目錄
Project_Deploy_Path=/opt/imoocc //工程部署目錄
Project_Start_Command=tomcat/bin/catalina.sh start //工程啟動方式
Project_Log_Path=/tmp/imoocc.log //啟動後日誌的查看方式
分享代碼如下:
# -*- coding: utf-8 -*-#!/usr/bin/python########################################################################## File Name: Jenkins_Project_Deploy.py# Program function: ueed for deployment code in CI server.# Author:Jeson# mail:[email protected]# Created Time: 一 6/20 19:24:33 2016#========================================================================importConfigParserimport sys
from sys import argv
import paramiko
defGennerate_cmd(Project_Name,CI_IP,Project_Code_File,Project_Exclude_File,Project_Backup_Dir,Project_Deploy_Path,Project_Start_Command,Project_Log_Path):
cmd =[]#生成備份命令ifProject_Backup_Dir:#生成備份原有文件
cmd.append("mkdir -p /opt/")
cmd.append("rsync -avzP %s %s && touch /tmp/CI_%s_backuptrue"%(Project_Deploy_Path,Project_Backup_Dir,Project_Name))#生成關閉原有進程命令
cmd.append(‘test -e /tmp/CI_%s_backuptrue && ps -auxgrep "name:%s"grep -v grepawk \‘{print $2}\‘xargs kill‘%(Project_Name,Project_Name))#生成命令-確認原來服務已經順利關閉
cmd.append(‘ps -auxgrep "name:%s"grep -v grepawk \‘{print $2}\‘&& touch /tmp/CI_killSucc ps -auxgrep "name:%s"grep -v grepawk \‘{print $2}\‘xargs kill -9‘%(Project_Name,Project_Name))#生成命令-用於同步新的代碼文件ifProject_Code_File=="":
cmd.append(‘test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s %s‘%(Project_Name,Project_Exclude_File,CI_IP,Project_Name,Project_Deploy_Path))else:
cmd.append(‘test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s/%s %s‘%(Project_Name,Project_Exclude_File,CI_IP,Project_Name,Project_Code_File,Project_Deploy_Path))#生成命令-用於啟動服務
cmd.append(Project_Start_Command)#生成命令-查看服務啟動後的日誌
cmd.append(‘tail -n 200 -f %s‘%Project_Log_Path)#生成命令-清理此次生成的臨時文件# cmd.append(‘rm -f /tmp/\*%s\*‘%Project_Name)return cmd
defLogin_Execute_Command(Project_IP,Project_Login_Port,Project_Login_User,Login_ISA_Key,cmds):Project_Port=int(Project_Login_Port)ifProject_Login_Portelse22ifProject_IPandProject_Login_UserandLogin_ISA_Key:
key = paramiko.RSAKey.from_private_key_file(Login_ISA_Key)
s = paramiko.SSHClient()
s.load_system_host_keys()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
s.connect(hostname=Project_IP,port=Project_Port,username=Project_Login_User,pkey=key)for cmd_item in cmds:
stdin,stdout,stderr=s.exec_command(cmd_item)print stdout.read()returnTrueelse:returnfalsedef main():if len(argv)>2:Config_File= argv[1]if argv[1]else"./Jenkins_Project_Deploy.conf "Project_Name= argv[2]if argv[2]else""else:print"Error 0:Input argv format error! ./Jenkins_Project_Deploy.py ./test.conf testname"
sys.exit()try:
cf =ConfigParser.ConfigParser()
cf.read(Config_File)
CI_IP = cf.get(Project_Name,"CI_IP")Project_Code_File= cf.get(Project_Name,"Project_Code_File")Project_Exclude_File= cf.get(Project_Name,"Project_Exclude_File")Project_Backup_Dir= cf.get(Project_Name,"Project_Backup_Dir")Project_Deploy_Path= cf.get(Project_Name,"Project_Deploy_Path")Project_Start_Command= cf.get(Project_Name,"Project_Start_Command")Project_Log_Path= cf.get(Project_Name,"Project_Log_Path")
execute_command =Gennerate_cmd(Project_Name,CI_IP,Project_Code_File,Project_Exclude_File,Project_Backup_Dir,Project_Deploy_Path,Project_Start_Command,Project_Log_Path)print"{Step 1: Command collected over!}",execute_command
Project_IP= cf.get(Project_Name,"Project_IP")Project_Login_Port= cf.get(Project_Name,"Project_Login_Port")Project_Login_User= cf.get(Project_Name,"Project_Login_User")Login_ISA_Key= cf.get(Project_Name,"Login_ISA_Key")exceptExceptionas e:print"Error 1: %s file open or read error!"%Config_File
sys.exit()print"{Step 2:Prepare to loging...}",Project_IP
result =Login_Execute_Command(Project_IP,Project_Login_Port,Project_Login_User,Login_ISA_Key,cmds=execute_command)if result isFalse:print"Error 3:Execute command failed!"if __name__ ==‘__main__‘:
main()
相關標簽: JAVA 雲計算 測試
本文原創發布於慕課網 ,轉載請註明出處,謝謝合作!
相關閱讀
-
刪除數組中的某個(多個)元素(分別用數組和集合的辦法刪除)
-
Java中Junit4測試實例
-
Spring+SpringMVC+MyBatis+easyUI整合優化篇(三)代碼測試
-
Spring+SpringMVC+MyBatis+easyUI整合優化篇(四)單元測試實例
-
Spring+SpringMVC+MyBatis+easyUI整合優化篇(五)MockMvc服務端的單元測試
添加評論
1條評論 weixin_xiaodian_01F老師為什麽不用python的fabric模塊自動部署打包
0 2017-09-14 23:13:40- 網站首頁
- 企業合作
- 人才招聘
- 聯系我們
- 講師招募
- 常見問題
- 意見反饋
- 慕課大學
- 友情鏈接
Copyright ? 2017 imooc.com All Rights Reserved | 京ICP備 13046642號-2
Jenkins持續集成-自動化部署腳本的實現《python》