因為工作需要,依舊還有一些主機為windows,在網(wǎng)上相關資料也不多,總結一下我的方式供各位參考.
使用ssh進行jenkins主節(jié)點與目標部署服務器進行通信,文件傳輸走scp協(xié)議,執(zhí)行執(zhí)行使用ssh命令遠程到目標主機進行執(zhí)行.
ssh調(diào)用命令腳本
使用ssh命令遠程服務器進行腳本調(diào)用的時候的流程是:
- 在本級ssh到目標主機
- 調(diào)用目標主機的腳本啟動tomcat,假如我們調(diào)用的是bin目錄下startup.bat
- 本機的終端窗口有輸出,遠程主機的tomcat啟動成功
- 關閉本級的ssh終端
- 遠程的tomcat隨之關閉
要解決的問題
ssh調(diào)用的進程的生命周期問題
查閱資料發(fā)現(xiàn)
針對上述情況在linux下的解決方案很多,這里描述下winsows的解決方案.
在這個回答下,采取了將tomcat做成Windows服務的方式,問題得到解決,具體的配置方式如下:
設置tomcat的環(huán)境變量
下載安裝版的Windows版tomcat,在bin目錄下分別為server.bat凛辣、startup.bat、shutdown.bat設置環(huán)境變量,如下所示
將tomcat注冊為服務
進入bin文件夾下執(zhí)行
service install 服務名稱
服務的啟動與停止
net stop server-name
net start server-name
將這兩條指令做成bat腳本,放在bin目錄下,供之后jenkins直接調(diào)用.
jenkins的終端輸出亂碼
在linux下遠程調(diào)用Windows的終端的時候,在jenksin的控制臺總是亂碼.查閱資料多數(shù)是說設置Jenkins的編碼為U8,但是我安裝的jenkins本身設置就是U8,后來發(fā)現(xiàn)在遠程調(diào)用的bat腳本第一行設置為
chcp 65001
表示切換到utf-8模式即可,之后輸出默認為英文且不會再亂碼.
是否有必要每次重啟Tomcat
場景
在實際使用的過程中,每次部署假如都需要重啟tomcat的話使得整個系統(tǒng)變得不穩(wěn)定,那么是否每次更新都要重啟tomcat呢?
首先我描述一下我遇到的一個問題,在jenkins中設置了一個重啟tomcat的腳本,腳本如下:
pipeline {
environment {
// 部署遠程主機ip地址,需要通過密鑰的方式設置免密登錄
remoteIp = "127.0.0.1"
remotePort='22'
// 失敗通知Email
email = "test@haigeek.cn"
// 遠程tomcat位置(windows要使用/來表示路徑)
tomcatPath = "E:/tomcat/apache-tomcat-8.5"
tomcatPathDisk = "E:"
}
agent any
tools {
maven 'maven-3.6.1'
}
stages {
stage('Deploy') {
steps {
withEnv(['JENKINS_NODE_COOKIE=dontKillMe']) {
sh '''
export BUILD_ID=dontKillMe
echo "開始使用scp傳輸文件"
echo "開始調(diào)用遠程tomcat進行重啟"
ssh -p ${remotePort} administrator@${remoteIp} "cd ${tomcatPath}/bin && ${tomcatPathDisk} && restart"
'''
}
}
}
}
}
上面的腳本核心功能就是調(diào)用遠程tomca下的restart腳本來重啟動tomcat,因為使用net stop tomcat 來關閉tomcat需要比較長時間,加上我們tomcat上運行的是dubbo項目,因此我直接使用taskkill的方式,根據(jù)dubbo端口來殺進程,結論是每次都可以成功殺死進程并重啟tomcat,如下圖,kill的腳本如下:
@echo off
chcp 65001
REM 設置dubbo端口號
set port=30109
for /f "tokens=5" %%i in ('netstat -aon ^| findstr ":%port%"') do (
set n=%%i
)
taskkill /pid %n% -F
jenkins的輸出如下:
但是當我將這個腳本集成在完整的pipeline中,會出現(xiàn)taskkill失敗的情況,報錯為PIDxxx為系統(tǒng)進程,無法殺死.
分析
分析了一下,唯一不同的是我在殺死tomcat之前將最新打包出的war包移動到了tomcat下,此時tomcat開始自動解壓并重新部署,注意此時進程已經(jīng)不是tomcat的進程id,而是切換為系統(tǒng)的進程.
在后期的測試中發(fā)現(xiàn)war包可以自動幫助我們熱更新,這個功能可以大大減少我們更新的速度.
解決
解決方法很簡單,將kill tomcat的指令放在移動war包之前,不再報錯.
完整Pipeline
// 持續(xù)集成腳本职烧,勿動
pipeline {
environment {
// 部署遠程主機ip地址,需要通過密鑰的方式設置免密登錄
remoteIp = "127.0.0.1"
remoteName = "administrator"
remotePort='22'
// 遠程tomcat位置(使用/來表示路徑)
tomcatPath = "C:/tomcat/apache-tomcat-8"
tomcatPathDisk = "C:"
}
agent any
tools {
maven 'maven-3.6.1'
}
stages {
stage('pullcode'){
steps{
git branch: 'dev', credentialsId: 'xxx', url: 'http://xxx.git'
}
}
stage('Build') {
steps {
sh '''
echo "開始編譯打包過程"
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
mvn clean && mvn package -DskipTests=true
'''
}
}
stage('Test'){
steps {
sh 'echo "Test stage"'
}
}
stage('Deploy') {
steps {
withEnv(['JENKINS_NODE_COOKIE=dontKillMe']) {
sh '''
export BUILD_ID=dontKillMe
echo "關閉tomcat,此步非必須,可使用war進行熱部署"
ssh -p ${remotePort} administrator@${remoteIp} "cd ${tomcatPath}/bin && ${tomcatPathDisk} && dubbokill"
echo "開始使用scp傳輸文件"
warfile1=$(ls 項目名稱/target/*.war)
scp -P ${remotePort} "${warfile1}" ${remoteName}@${remoteIp}:${tomcatPath}/webapps
warfile2=$(ls 項目名稱/target/*.war)
scp -P ${remotePort} "${warfile2}" ${remoteName}@${remoteIp}:${tomcatPath}/webapps
echo "開始調(diào)用遠程tomcat進行重啟,此步驟非必須"
ssh -p ${remotePort} administrator@${remoteIp} "cd ${tomcatPath}/bin && ${tomcatPathDisk} && servicestart"
'''
}
}
}
}
}