jenkins流水線,實現多臺伺服器批量釋出、回滾
阿新 • • 發佈:2022-03-09
/* 1、指令碼中儘量使用雙引號,單引號中使用變數會出問題 2、遠端執行shell指令碼中的內部的“$”符號需要斜槓轉義,包括變數和正則表示式的使用,流水線中的全域性變數則不需要轉義直接使用 3、遠端執行shell指令碼說明 釋出: 1)使用“Publish over SSH”外掛上傳jar包到伺服器 2)修改jar檔名稱,在名稱後面加上構建時間,最終jar檔名稱類似gateway-1.0.7.22020914.jar,jar檔名新增時間這步也可以由maven實現 3)生成軟連線 4)nohup啟動java程式 5)輸出20s日誌 回滾: 1)停止程序 2)軟連線指向回滾版本的jar檔案 3)啟動java程式 4)輸出20s日誌 */ pipeline { agent any environment { /* BUILD_TIMESTAMP 構建時間,由 Build Timestamp外掛提供,這裡在全域性配置格式改成了yyMMddHHmm,也可以使用groovy的TimeZone.getTimeZone("Asia/Shanghai")函式實現 */ PROJECT_NAME = "golife" // 專案名稱 SERVICE_NAME= "member" // 服務名稱 BRANCH_NAME = "master" // gitlab分支 GIT_PATH = "GITURL" // 專案URL GIT_AUTH_ID = "git憑證id" // git憑證id GIT_BRANCH = "master" // git分支 } // maven工具,在系統管理-全域性工具配置-Maven,如果沒有新增一個即可,這裡的“maven3.6.3”為新增mavne的“name” tools { maven "maven" } options { timestamps() //設定在專案列印日誌時帶上對應時間 disableConcurrentBuilds() //不允許同時執行流水線,被用來防止同時訪問共享資源等 timeout(time: 5, unit: "MINUTES") // 設定流水線執行超過n分鐘,Jenkins將中止流水線 buildDiscarder(logRotator(numToKeepStr: "10")) // 表示保留n次構建歷史 } //引數化構建過程,可在流水線語法http://{JENKINS URL}/job/piptt/pipeline-syntax/中選擇“properties: Set job properties”生成流水線 parameters{ // 釋出選項--選項引數 choice( choices: ['deploy', 'rollback','start','restart','stop'], description: '''釋出選項: 釋出:deploy 回滾:rollback 啟動:start 重啟:restart 停止:stop ''', name: 'ACTION' ) // 要執行的伺服器--多選框引數(需安裝外掛Extended Choice Parameter) extendedChoice( description: '選擇需要執行的伺服器', multiSelectDelimiter: ',', name: 'Release_servers', quoteValue: false, saveJSONParameterToFile: false, type: 'PT_CHECKBOX', value: '192.168.1.100,192.168.1.101,192.168.1.102,192.168.1.103', // Publish over SSH外掛新增的伺服器名,安裝好外掛後再系統管理-系統配置-找到“Publish over SSH”新增伺服器 visibleItemCount: 10 ) // 釋出版本號--字串引數 string( defaultValue: '1.0.7', description: '''釋出版本號,僅釋出操作需要填寫。 該版本號為maven打包後jar包名稱的版本號,如gateway-1.0.7,填寫 1.0.7''', name: 'RELEASE_VERSION', trim: true ) // 回滾版本號--字串引數 string( description: '''回滾版本號,僅回滾操作需要填寫 可在構建歷史日誌中,搜尋“RELEASE VERION”找到,格式為:1.0.7.22010456''', name: 'BACK_VERSION', trim: true ) } stages { stage("列印資訊") { //列印資訊 steps { echo "列印資訊" echo "jenkins任務名: ${JOB_NAME}" echo "專案名: ${PROJECT_NAME}" echo "服務名:${SERVICE_NAME}" echo "執行動作: ${ACTION}" echo "gitlab分支名: ${BRANCH_NAME}" echo "build_id: ${BUILD_ID}" echo "工作空間: ${WORKSPACE}" echo "釋出伺服器: ${Release_servers}" } } stage("拉取程式碼") { // 僅當${ACTION}=="deploy"時,再執行此stage,詳情檢視官網when指令https://www.jenkins.io/zh/doc/book/pipeline/syntax/#when when { environment name:"ACTION", value: "deploy" } // 流水線語法中選擇“checkout: Check out from version control”生成 steps { script { checkout([ $class: "GitSCM", branches: [[name: "${GIT_BRANCH}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${GIT_AUTH_ID}", url: "${GIT_PATH}"]] ]) } } } stage("maven構建") { when { environment name:"ACTION", value: "deploy" } steps { sh "mvn clean install -f ./pom.xml" } } stage("釋出") { /* when { environment name:"ACTION", value: "rollback" not { environment name:"Release_servers", value:"" } } 這裡的when指令可以多用一個not來判斷構建的時候是否有選擇釋出的伺服器,為了直觀的看到我這裡在scritp裡面判斷了下,如果沒有選擇伺服器則輸出“沒有可用於執行的伺服器” */ when { environment name:"ACTION", value: "deploy" } steps { script { if (Release_servers.length() == 0) { println("沒有可用於執行的伺服器") } else { for ( ip in Release_servers.tokenize(",")) { sshPublisher ( publishers: [ sshPublisherDesc ( configName: "${ip}", transfers: [ sshTransfer ( cleanRemote: false, excludes: "", execCommand: """ echo "###########################################################################################################################################################################################################################" mkdir /var/log/${PROJECT_NAME}/${SERVICE_NAME} -p mkdir /opt/${PROJECT_NAME}/link-jar/ -p SERVICE_PID=`pgrep -f "java.*${SERVICE_NAME}{0,20}\$"` # 服務執行pid mv /opt/${PROJECT_NAME}/jar/${SERVICE_NAME}/${SERVICE_NAME}-${RELEASE_VERSION}.jar /opt/${PROJECT_NAME}/jar/${SERVICE_NAME}/${SERVICE_NAME}-${RELEASE_VERSION}.${BUILD_TIMESTAMP}.jar if [ \$? != "0" ] then echo "${ip}上找不到版本號為${RELEASE_VERSION}的${SERVICE_NAME},請檢查後重新構建" exit 145 else echo "${ip}:開始部署${SERVICE_NAME}" ln -snf /opt/${PROJECT_NAME}/jar/${SERVICE_NAME}/${SERVICE_NAME}-${RELEASE_VERSION}.${BUILD_TIMESTAMP}.jar /opt/${PROJECT_NAME}/link-jar/${PROJECT_NAME}-${SERVICE_NAME} kill -9 "\${SERVICE_PID}" nohup java -jar /opt/${PROJECT_NAME}/link-jar/${PROJECT_NAME}-${SERVICE_NAME} > /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.log 2>&1 & echo -e "\n啟動日誌將持續輸出20s時間,如果沒有輸出日誌,則表示釋出失敗\n" timeout 20 tail -f /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.log sleep 1 echo "< RELEASE VERION: ${RELEASE_VERSION}.${BUILD_TIMESTAMP} >" fi """, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: "[, ]+", remoteDirectory: "/${PROJECT_NAME}/jar/${SERVICE_NAME}", remoteDirectorySDF: false, removePrefix: "${SERVICE_NAME}/target", sourceFiles: "**/${SERVICE_NAME}*.jar" ) ], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true ) ] ) } } } } } stage('回滾') { when { environment name:"ACTION", value: "rollback" } steps { script { if (Release_servers.length() == 0) { println("沒有可用於執行的伺服器") } else { for ( ip in Release_servers.tokenize(",")) { sshPublisher( publishers: [ sshPublisherDesc( configName: "${ip}", transfers: [ sshTransfer(cleanRemote: false, excludes: '', execCommand: """ echo "###########################################################################################################################################################################################################################" mkdir /var/log/${PROJECT_NAME}/${SERVICE_NAME} -p mkdir /opt/${PROJECT_NAME}/link-jar/ -p SERVICE_PID=`pgrep -f "java.*${SERVICE_NAME}{0,20}\$"` # 服務執行pid if [ -f "/opt/${PROJECT_NAME}/jar/${SERVICE_NAME}/${SERVICE_NAME}-${BACK_VERSION}.jar" ] then echo "${ip}:開始部署${SERVICE_NAME}" ln -snf /opt/${PROJECT_NAME}/jar/${SERVICE_NAME}/${SERVICE_NAME}-${BACK_VERSION}.jar /opt/${PROJECT_NAME}/link-jar/${PROJECT_NAME}-${SERVICE_NAME} kill -9 "\${SERVICE_PID}" nohup java -jar /opt/${PROJECT_NAME}/link-jar/${PROJECT_NAME}-${SERVICE_NAME} > /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.${ACTION}.log 2>&1 & echo -e "\n啟動日誌將持續輸出20s時間,如果沒有輸出日誌,則表示回滾失敗\n" timeout 20 tail -f /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.${ACTION}.log sleep 1 else echo "${ip}上找不到版本號為${BACK_VERSION}的${SERVICE_NAME},請檢查後重新構建" exit 145 fi """, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '' ) ], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true ) ] ) } } } } } stage('啟動') { when { environment name:"ACTION", value: "start" } steps { script { if (Release_servers.length() == 0) { println("沒有可用於執行的伺服器") } else { for ( ip in Release_servers.tokenize(",")) { sshPublisher( publishers: [ sshPublisherDesc( configName: "${ip}", transfers: [ sshTransfer(cleanRemote: false, excludes: '', execCommand: """ echo "###########################################################################################################################################################################################################################" SERVICE_PID=`pgrep -f "java.*${SERVICE_NAME}{0,20}\$"` # 服務執行pid if [ \$? != "0" ] then echo "${ip}:正在啟動${SERVICE_NAME}" nohup java -jar /opt/${PROJECT_NAME}/link-jar/${PROJECT_NAME}-${SERVICE_NAME} > /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.${ACTION}.log 2>&1 & echo -e "\n啟動日誌將持續輸出20s時間,如果沒有輸出日誌,則表示回滾失敗\n" timeout 20 tail -f /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.${ACTION}.log sleep 1 else echo "${ip}上${SERVICE_NAME}已啟動,無需執行" exit 145 fi """, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '' ) ], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true ) ] ) } } } } } stage('重啟') { when { environment name:"ACTION", value: "restart" } steps { script { if (Release_servers.length() == 0) { println("沒有可用於執行的伺服器") } else { for ( ip in Release_servers.tokenize(",")) { sshPublisher( publishers: [ sshPublisherDesc( configName: "${ip}", transfers: [ sshTransfer(cleanRemote: false, excludes: '', execCommand: """ echo "###########################################################################################################################################################################################################################" SERVICE_PID=`pgrep -f "java.*${SERVICE_NAME}{0,20}\$"` # 服務執行pid echo "${ip}:正在重啟${SERVICE_NAME}" kill -9 "\${SERVICE_PID}" nohup java -jar /opt/${PROJECT_NAME}/link-jar/${PROJECT_NAME}-${SERVICE_NAME} > /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.${ACTION}.log 2>&1 & echo -e "\n啟動日誌將持續輸出20s時間,如果沒有輸出日誌,則表示回滾失敗\n" timeout 20 tail -f /var/log/${PROJECT_NAME}/${SERVICE_NAME}/${SERVICE_NAME}-${BUILD_TIMESTAMP}.${ACTION}.log sleep 1 """, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '' ) ], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true ) ] ) } } } } } stage('停止') { when { environment name:"ACTION", value: "stop" } steps { script { if (Release_servers.length() == 0) { println("沒有可用於執行的伺服器") } else { for ( ip in Release_servers.tokenize(",")) { sshPublisher( publishers: [ sshPublisherDesc( configName: "${ip}", transfers: [ sshTransfer(cleanRemote: false, excludes: '', execCommand: """ echo "###########################################################################################################################################################################################################################" SERVICE_PID=`pgrep -f "java.*${SERVICE_NAME}{0,20}\$"` # 服務執行pid if [ \$? == "0" ] then echo "${ip}:正在停止服務${SERVICE_NAME}" kill -9 "\${SERVICE_PID}" echo "服務${SERVICE_NAME}"停止成功 else echo "${ip}上${SERVICE_NAME}未啟動,無需執行" exit 145 fi """, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '' ) ], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true ) ] ) } } } } } } }