最近为公司做Jenkins部署改造,本文为我这几天的研究结果
之前断断续续学过Jenkins,但从未成功过,原因在于他们都是简单的使用普通项目,我怎么就看不懂,各种配置之间没有逻辑让我有点晕
此次机会,我重新翻阅了一遍《Jenkins2.x实践指南》,不得不说,带着问题的看书让我效率非常高,一个小时左右我就明白该怎么做了
这次我使用的是pipeline方式实现,因为这种方式更具逻辑性,前后连贯,容易理解。不过我们得考虑到团队内其他成员的知识储备,所以pipeline文件内的我加满了必要的注释,帮助其他人员快速理解学习
以下是我编写的pipeline脚本,基于其他项目的改造,各位根据需要进行自己开发,请不要直接使用(每个项目有每个项目的特性,需要结合自己的情况编写),明白我的意思即可。
要想成功运行SSH,需要安装插件
插件名称: SSH Pipeline Steps
使用说明: https://github.com/jenkinsci/ssh-steps-plugin#pipeline-steps
- // 代表整条流水线
- pipeline {
- agent any
-
- parameters {
- gitParameter(name: 'branch', defaultValue: 'origin/master', type: 'PT_BRANCH')
- choice(name: '请选择操作', choices: [ "拉取代码-编译-打包-运行", "重启", "启动", "停止" ])
- }
-
- // 设置环境变量
- environment {
- ACTION = "${params.请选择操作}"
-
- // ========== 远程服务器信息 ================
- REMOTE_HOST = "${REMOTE_LOCAL_HOST_27}"
- REMOTE_USER = "${REMOTE_LOCAL_USER_27}"
- REMOTE_PASSWORD = "${REMOTE_LOCAL_PASSWORD_27}"
- // 需要传输的文件路径
- FILE_NAME = ""
- SOURCE_FILE_PATH = ""
- // 传输到目标服务器的位置
- TARGET_PATH = ""
- // jar包备份路径
- BACKUP_PATH = ""
- // 运行,启动位置
- RUN_PATH = ""
- }
-
- // pipeline选项
- options {
- // 保存最近历史构建记录数量
- buildDiscarder(logRotator(numToKeepStr: '10'))
- // 禁止pipeline同时执行
- disableConcurrentBuilds()
- // 失败时重试总次数
- // retry(2)
- // pipeline执行时间过长,超过timeout时间就停止掉pipeline
- timeout(time: 3, unit: 'MINUTES')
- }
-
- // 阶段容器
- stages {
- // 阶段:重新构建
- stage('build and run') {
- when {
- environment name: 'ACTION', value: '拉取代码-编译-打包-运行'
- }
- steps {
- script {
- echo "==================== 开始重新构建项目 ========================"
- echo "====================== 项目打包 ============================"
- sh "mvn clean package -DskipTests -Dmaven.compile.fork=true -U -B -pl motionplus-visual/motionplus-codegen -am -amd"
-
-
- echo "================= 将jar包发送到远程服务器 ====================="
-
- def remote = [:]
- remote.name = "${REMOTE_HOST}"
- remote.host = "${REMOTE_HOST}"
- remote.user = "${REMOTE_USER}"
- remote.password = "${REMOTE_PASSWORD}"
- remote.allowAnyHosts = true
-
- sshPut remote: remote, from: "${SOURCE_FILE_PATH}" , into: "${TARGET_PATH}"
-
- echo "备份"
- sshCommand remote: remote, command: "cp ${RUN_PATH}${FILE_NAME}.jar ${BACKUP_PATH}${FILE_NAME}-" + '$(date +%Y-%m-%d-%H%M%S).jar'
-
- echo "关闭"
- try {
- sshCommand remote: remote, command: "jps -l | grep ${FILE_NAME}.jar | cut -d' ' -f1 | xargs kill"
- } catch(err) {
- echo "关闭失败:${FILE_NAME}没有启动"
- }
-
- echo "替换新包"
- sshCommand remote: remote, command: "cp ${TARGET_PATH}${FILE_NAME}.jar ${RUN_PATH}"
-
- // 睡眠5秒,等待应用停止完毕再启动
- sleep(5)
-
- echo "启动"
- sshCommand remote: remote, command: "java -javaagent:/usr/local/skywalking/agent/skywalking-agent.jar -Dskywalking.agent.service_name=${FILE_NAME} -Dskywalking.collector.backend_service=127.0.0.1:11800 -jar ${RUN_PATH}${FILE_NAME}.jar --spring.profiles.active=test >" + '/logs/${FILE_NAME}/log-$(date +%Y%m%d).txt 2>&1 &'
-
- }
- }
- }
-
- // 阶段:启动
- stage('start') {
- when {
- environment name: 'ACTION', value: '启动'
- }
- steps {
- script {
- echo "====================== 启动项目 =========================="
- def remote = [:]
- remote.name = "${REMOTE_HOST}"
- remote.host = "${REMOTE_HOST}"
- remote.user = "${REMOTE_USER}"
- remote.password = "${REMOTE_PASSWORD}"
- remote.allowAnyHosts = true
-
- sshCommand remote: remote, command: "java -javaagent:/usr/local/skywalking/agent/skywalking-agent.jar -Dskywalking.agent.service_name=${FILE_NAME} -Dskywalking.collector.backend_service=127.0.0.1:11800 -jar ${RUN_PATH}${FILE_NAME}.jar --spring.profiles.active=test >" + '/logs/${FILE_NAME}/log-$(date +%Y%m%d).txt 2>&1 &'
- }
- }
- }
-
- // 阶段:停止
- stage('stop') {
- when {
- environment name: 'ACTION', value: '停止'
- }
- steps {
- script {
- echo "====================== 停止项目 =========================="
- def remote = [:]
- remote.name = "${REMOTE_HOST}"
- remote.host = "${REMOTE_HOST}"
- remote.user = "${REMOTE_USER}"
- remote.password = "${REMOTE_PASSWORD}"
- remote.allowAnyHosts = true
-
- try {
- sshCommand remote: remote, command: "jps -l | grep ${FILE_NAME}.jar | cut -d' ' -f1 | xargs kill"
- } catch(err) {
- echo "关闭失败:${FILE_NAME}没有启动"
- }
- }
- }
- }
- // 阶段:重启
- stage('restart') {
- when {
- environment name: 'ACTION', value: '重启'
- }
- steps {
- script {
- echo "====================== 重启项目 =========================="
- echo "关闭"
-
- def remote = [:]
- remote.name = "${REMOTE_HOST}"
- remote.host = "${REMOTE_HOST}"
- remote.user = "${REMOTE_USER}"
- remote.password = "${REMOTE_PASSWORD}"
- remote.allowAnyHosts = true
-
- try {
- sshCommand remote: remote, command: "jps -l | grep ${FILE_NAME}.jar | cut -d' ' -f1 | xargs kill"
- } catch(err) {
- echo "关闭失败:${FILE_NAME}没有启动"
- }
-
- // 睡眠5秒,等待应用停止完毕再启动
- sleep(5)
-
- sshCommand remote: remote, command: "java -javaagent:/usr/local/skywalking/agent/skywalking-agent.jar -Dskywalking.agent.service_name=${FILE_NAME} -Dskywalking.collector.backend_service=127.0.0.1:11800 -jar ${RUN_PATH}${FILE_NAME}.jar --spring.profiles.active=test >" + '/logs/${FILE_NAME}/log-$(date +%Y%m%d).txt 2>&1 &'
- }
- }
- }
- }
-
- // 整个pipeline完成后
- post {
-
- // 状态为失败执行
- failure {
- echo "====================== 运行失败 =========================="
- }
-
- // 状态为成功执行
- success {
- echo "====================== 运行成功 =========================="
- // mail subject: '关于xxx日的构建反馈-成功', body: '构建成功了', from: 'xxx@163.com',, to: 'to@163.com' // 可以邮件通知或者webhook
- }
- }
- }
由于我不怎么会groovy,所以代码有大量冗余,如果各位能够告诉我怎么抽出来,不胜感激。
另外我也将groovy书籍加入了我的书架,偶尔翻翻,由于是英文的,学起来还是有点吃力,不过当初也看在可以练习阅读能力倒也挺好
没有花太多时间在这个上面,是因为这也不是我的主业,慢慢优化吧
这是第二个的
这个项目的特性就是用SSH做的,还是非MAVEN项目,所以使用了ANT打包,然后使用Tomcat运行
- // 代表整条流水线
- pipeline {
- agent any
-
- parameters {
- choice(name: 'branch', choices: ['master', 'dev', 'test'], description: '请选择构建分支')
- }
-
- // 设置环境变量
- environment {
- // 安装Jenkins的操作系统类正在停止tomcat型:可选值 windows / linux
- OS = "linux"
- // 本机:ant自动生成打包配置文件位正在停止tomcat置(不带文件后缀)
- ANT_GENERATE_BUILD_PATH = "/usr/lib/jenkins/generate-build"
- // 本机:ant位置
- ANT_HOME = "/usr/lib/jenkins/apache-ant-1.9.16"
- // 本机:tomcat home目录路径
- TOMCAT_HOME = "/usr/lib/jenkins/apache-tomcat-8.5.75"
-
- // 项目部署类型 local(本地) remote(远程服务器)
- DEPLOY_TYPE = "remote"
-
- /// ========== 如果部署到远程服务器 就填写下面的内容 ============
- // windows / linux
- REMOTE_OS = "linux"
- REMOTE_HOST = ""
- REMOTE_USER = ""
- REMOTE_PASSWORD = ""
- // windows 路径示例:/D:/developer/apache-tomcat-8.5.75 注意前面要加个/
- REMOTE_TOMCAT_HOME = ""
-
- // 如果部署的是远程windows,就填写下面tomcat服务名称
- REMOTE_WINDOWS_TOMCAT_SERVICE_NAME = "Tomcat"
-
- }
-
- // pipeline选项
- options {
- // 保存最近历史构建记录数量
- buildDiscarder(logRotator(numToKeepStr: '10'))
- // 禁止pipeline同时执行
- disableConcurrentBuilds()
- // 失败时重试总次数
- // retry(2)
- // pipeline执行时间过长,超过timeout时间就停止掉pipeline
- timeout(time: 3, unit: 'MINUTES')
- }
-
- // 阶段容器
- stages {
- // 流水线的阶段
- // 1.拉取代码
- stage("check out"){
- // 步骤
- steps {
- echo "========================== 拉取代码 ============================="
- git branch: 'master', credentialsId: '', url: ''
- echo "======================== 拉取代码完毕 ============================="
- }
- }
-
- // 2.打包项目(本机windows环境打包) |||||||||||未测试
- stage('build-windows') {
- // 当条件满足了才执行当前 stage
- when {
- // 环境变量的OS变量需要 等于 windows
- environment name: 'OS', value: 'windows'
- }
- steps {
- echo "====================== Windows下开始打包项目 ============================"
- echo "开始生成ant打包配置文件"
- // 生成配置文件
- // 第一个参数tomcat安装目录:将目录传入ant build.xml里,到时候将打包出来的包复制到tomcat/webapp下
- // 第一个参数项目名称:打包出来的文件名
- // 第三个参数源码路径:将生成的配置文件放到源码根目录下
- bat "${ANT_GENERATE_BUILD_PATH}.bat ${TOMCAT_HOME} ${JOB_NAME} ${WORKSPACE}"
- echo "开始执行ant打包命令."
- // 开始打包
- bat "${ANT_HOME}/bin/ant -buildfile ${WORKSPACE}/build.xml"
- echo "=========================== 项目打包完毕 =============================="
- }
- }
-
- // 2.打包项目(本机linux环境打包)
- stage('build-linux') {
- when {
- environment name: 'OS', value: 'linux'
- }
- steps {
- echo "====================== Linux下开始打包项目 ============================="
- echo "开始生成ant打包配置文件"
- sh "JENKINS_NODE_COOKIE=dontKillMe sh ${ANT_GENERATE_BUILD_PATH}.sh ${TOMCAT_HOME} ${JOB_NAME} ${WORKSPACE}"
- echo "开始执行ant打包命令"
- sh "JENKINS_NODE_COOKIE=dontKillMe sh ${ANT_HOME}/bin/ant -buildfile ${WORKSPACE}/build.xml"
- echo "=========================== 项目打包完毕 =============================="
- }
- }
-
- // 3.启动项目:远程windows上启动
- stage('run-remote-windows') {
- when {
- // 当部署类型是远程服务器 并且 远程服务器是windows才执行
- environment name: 'DEPLOY_TYPE', value: 'remote'
- environment name: 'REMOTE_OS', value: 'windows'
- }
- steps {
- script {
- echo "=============== 部署到远程服务器[Windows] ============================="
-
- def remote = [:]
- remote.name = "remote-windows"
- remote.host = "${REMOTE_HOST}"
- remote.user = "${REMOTE_USER}"
- remote.password = "${REMOTE_PASSWORD}"
- remote.allowAnyHosts = true
-
- try {
- sshCommand remote: remote, command: "net stop ${REMOTE_WINDOWS_TOMCAT_SERVICE_NAME}"
- } catch(err) {
- echo "停止失败:Tomcat没有启动"
- }
-
- sshPut remote: remote, from: "${WORKSPACE}/target/war/${JOB_NAME}.war" , into: "${REMOTE_TOMCAT_HOME}/webapps/"
- echo "====================== 打包文件上传成功 ============================="
-
- sshCommand remote: remote, command: "net start ${REMOTE_WINDOWS_TOMCAT_SERVICE_NAME}"
- echo "====================== Tomcat启动成功 ============================="
- }
- }
- }
-
- // 3.启动项目:远程linux上启动
- stage('run-remote-linux') {
- when {
- // 当部署类型是远程服务器 并且 远程服务器是linux才执行
- environment name: 'DEPLOY_TYPE', value: 'remote'
- environment name: 'REMOTE_OS', value: 'linux'
- }
- steps {
- script {
- echo "=============== 部署到远程服务器[Linux] ============================="
- def remote = [:]
- remote.name = 'remote-linux'
- remote.host = "${REMOTE_HOST}"
- remote.user = "${REMOTE_USER}"
- remote.password = "${REMOTE_PASSWORD}"
- remote.allowAnyHosts = true
-
- try {
- sshCommand remote: remote, command: "sh ${REMOTE_TOMCAT_HOME}/bin/shutdown.sh"
- } catch(err) {
- echo "停止失败:Tomcat没有启动"
- }
- sshPut remote: remote, from: "${WORKSPACE}/target/war/${JOB_NAME}.war", into: "${REMOTE_TOMCAT_HOME}/webapps/"
-
- echo "====================== 打包文件上传成功 ============================="
-
- sshCommand remote: remote, command: "sh ${REMOTE_TOMCAT_HOME}/bin/startup.sh"
- echo "====================== Tomcat启动成功 ============================="
- }
- }
- }
-
- // 3.启动项目:本地windows上启动 |||||||||||未测试
- stage('run-local-windows') {
- when {
- // 环境变量的OS变量需要 等于 windows
- environment name: 'DEPLOY_TYPE', value: 'local'
- environment name: 'OS', value: 'windows'
- }
- steps {
- echo "============ 将打包文件复制到Tomcat Webapps下 ==============="
- sh "cp ${WORKSPACE}/target/war/${JOB_NAME}.war ${TOMCAT_HOME}/webapps/"
- echo "===================== 开始启动项目 ========================="
- echo "开始运行项目"
- echo "正在停止tomcat"
- bat '${TOMCAT_HOME}/bin/shutdown.bat'
- echo "停止成功"
- echo "正在启动tomcat"
- bat '${TOMCAT_HOME}/bin/startup.bat'
- echo "启动成功"
- echo "====================== 启动成功 =========================="
- }
- }
-
- // 3.启动项目:本地linux上启动
- stage('run-local-linux') {
- when {
- environment name: 'DEPLOY_TYPE', value: 'local'
- environment name: 'OS', value: 'linux'
- }
- steps {
- script {
- echo "============ 将打包文件复制到Tomcat Webapps下 ==============="
- sh "cp ${WORKSPACE}/target/war/${JOB_NAME}.war ${TOMCAT_HOME}/webapps/"
- echo "===================== 开始启动项目 ========================="
- echo "开始运行项目"
- echo "正在停止tomcat"
- try {
- sh 'JENKINS_NODE_COOKIE=dontKillMe sh ${TOMCAT_HOME}/bin/shutdown.sh'
- } catch (err) {
- echo "停止失败:Tomcat没有启动"
- }
-
- echo "正在启动tomcat"
- sh 'JENKINS_NODE_COOKIE=dontKillMe sh ${TOMCAT_HOME}/bin/startup.sh'
- echo "启动成功"
- echo "====================== 启动成功 =========================="
- }
- }
- }
- }
-
- // 整个pipeline完成后
- post {
-
- // 状态为失败执行
- failure {
- echo "====================== 部署失败 =========================="
- }
-
- // 状态为成功执行
- success {
- echo "====================== 部署成功 =========================="
- // mail subject: '关于xxx日的构建反馈-成功', body: '构建成功了', from: 'xxx@163.com',, to: 'to@163.com' // 可以邮件通知或者webhook
- }
- }
- }
-
-
说几个注意点
pipeline的${} 变量必须写在 双引号" " 字符串里面才能被解析
pipeline里运行tomcat会启动不起来 需要前面加 JENKINS_NODE_COOKIE=dontKillMe 具体看上面代码