Jenkins使用Pipeline部署項目到遠程windows

因為工作需要,依舊還有一些主機為windows,在網上相關資料也不多,總結一下我的方式供各位參考.
使用ssh進行jenkins主節點與目標部署服務器進行通信,文件傳輸走scp協議,執行執行使用ssh命令遠程到目標主機進行執行.

ssh調用命令腳本

使用ssh命令遠程服務器進行腳本調用的時候的流程是:

  1. 在本級ssh到目標主機
  2. 調用目標主機的腳本啟動tomcat,假如我們調用的是bin目錄下startup.bat
  3. 本機的終端窗口有輸出,遠程主機的tomcat啟動成功
  4. 關閉本級的ssh終端
  5. 遠程的tomcat隨之關閉

要解決的問題

ssh調用的進程的生命周期問題

查閱資料發現

image-20190704223510253.png

針對上述情況在linux下的解決方案很多,這里描述下winsows的解決方案.

在這個回答下,采取了將tomcat做成Windows服務的方式,問題得到解決,具體的配置方式如下:

設置tomcat的環境變量

下載安裝版的Windows版tomcat,在bin目錄下分別為server.bat、startup.bat、shutdown.bat設置環境變量,如下所示

image-20190704224910131.png

將tomcat注冊為服務

進入bin文件夾下執行

service install 服務名稱

[圖片上傳中...(image-20190704230244896.png-4869a1-1562942345129-0)]

服務的啟動與停止

net stop server-name
net start server-name
image-20190704230244896.png

將這兩條指令做成bat腳本,放在bin目錄下,供之后jenkins直接調用.

image-20190704230544740.png

jenkins的終端輸出亂碼

在linux下遠程調用Windows的終端的時候,在jenksin的控制臺總是亂碼.查閱資料多數是說設置Jenkins的編碼為U8,但是我安裝的jenkins本身設置就是U8,后來發現在遠程調用的bat腳本第一行設置為

chcp 65001

表示切換到utf-8模式即可,之后輸出默認為英文且不會再亂碼.

是否有必要每次重啟Tomcat

場景

在實際使用的過程中,每次部署假如都需要重啟tomcat的話使得整個系統變得不穩定,那么是否每次更新都要重啟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 "開始調用遠程tomcat進行重啟"
                        ssh  -p ${remotePort} administrator@${remoteIp} "cd ${tomcatPath}/bin && ${tomcatPathDisk} && restart"
                    '''
                }
            }
        }
    }
}

上面的腳本核心功能就是調用遠程tomca下的restart腳本來重啟動tomcat,因為使用net stop tomcat 來關閉tomcat需要比較長時間,加上我們tomcat上運行的是dubbo項目,因此我直接使用taskkill的方式,根據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的輸出如下:

image-20190712221521459.png

但是當我將這個腳本集成在完整的pipeline中,會出現taskkill失敗的情況,報錯為PIDxxx為系統進程,無法殺死.

分析

分析了一下,唯一不同的是我在殺死tomcat之前將最新打包出的war包移動到了tomcat下,此時tomcat開始自動解壓并重新部署,注意此時進程已經不是tomcat的進程id,而是切換為系統的進程.

在后期的測試中發現war包可以自動幫助我們熱更新,這個功能可以大大減少我們更新的速度.

解決

解決方法很簡單,將kill tomcat的指令放在移動war包之前,不再報錯.

完整Pipeline

// 持續集成腳本,勿動

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 "開始調用遠程tomcat進行重啟,此步驟非必須"
                        ssh  -p ${remotePort} administrator@${remoteIp} "cd ${tomcatPath}/bin && ${tomcatPathDisk} && servicestart"
                    '''
                }
            }
        }
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容