【轻松掌握】Jenkins入门指南:构建高效的CI/CD Pipeline

文章目录

前言

本文提供了一份全面的Jenkins学习指南,旨在帮助你理解和掌握这一强大的持续集成/持续部署(CI/CD)工具。文章详细介绍了Jenkins的安装、配置过程,以及如何与Maven和Git等工具集成,帮助你从零开始搭建自己的CI/CD环境。

在学习过程中,你将逐步了解如何设置Jenkins、安装必要的插件,通过示例项目,最终实现应用的自动化部署。特别是通过Jenkins Pipeline,你将学会如何定义构建、部署等各个阶段。

快速使用:只看配置相关内容+最终版Pipeline+脚本解释即可

安装部署

Jenkins+Maven+Git

英文官网:https://www.jenkins.io

中文官网:https://www.jenkins.io/zh/

安装JDK

Linux检查是否安装了JDK

java -version

如果没找到就安装一个

查询所有可以安装版本

yum search java|grep jdk

在这里插入图片描述

下载安装JDK11(Jenkins支持一件安装插件的JDK版本最低是11,所以这里安装了11)

yum install -y java-11-openjdk

在这里插入图片描述

修改默认JDK版本

alternatives --config java
这里指定为11,避免后面一系列的问题

在这里插入图片描述

安装Jenkins

在这里插入图片描述

下载不了点这里

https://updates.jenkins.io/download/war/

下载Jenkins

下载2.387.3(目前最新插件最低支持的Jenkins版本是2.387.3)

在这里插入图片描述

在这里插入图片描述

运行Jenkins

/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64/bin/java -jar jenkins_2.387.3.war --httpPort=8080

在这里插入图片描述

访问页面

http://xxx.xxx.xx.xxx:8080/

填写管理员密码

在这里插入图片描述

这个密码存在于启动时的控制台界面上,也可以去下方路径的文件中查找

在这里插入图片描述

安装推荐的插件

在这里插入图片描述

Maven安装

下载

下载链接:https://maven.apache.org/download.cgi

在这里插入图片描述

上传到Linux

解压

mkdir -p /opt/maven-3.9.8
tar zxvf apache-maven-3.9.8-bin.tar.gz -C /opt/maven-3.9.8

配置镜像

<mirrors>
    <!-- 优先使用阿里云镜像 -->
    <mirror>
        <id>aliyun</id>
        <name>Aliyun Maven Mirror</name>
        <url>https://maven.aliyun.com/repository/public</url>
        <mirrorOf>central</mirrorOf>
    </mirror>

    <!-- 如果阿里云镜像不可用,再使用 Maven Central -->
    <mirror>
        <id>central</id>
        <name>Maven Central Repository</name>
        <url>https://repo.maven.apache.org/maven2</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
</mirrors>

运行

/opt/maven-3.9.8/apache-maven-3.9.8/bin/mvn

在这里插入图片描述

查看Maven使用的JDK版本

/opt/maven-3.9.8/apache-maven-3.9.8/bin/mvn -v

在这里插入图片描述

Jenkins安装Maven插件

在这里插入图片描述

在这里插入图片描述

创建Demo项目

示例代码仓库:https://github.com/ChenJiahao0205/Jenkins-Learning

在这里插入图片描述

在这里插入图片描述

创建Jenkins任务

在这里插入图片描述

在这里插入图片描述

填写代码仓库地址

在这里插入图片描述

Linux安装GIT解决报错

yum install git

验证

在这里插入图片描述

配置Maven版本

在这里插入图片描述

配置刚才安装Maven的路径即可

在这里插入图片描述

保存完回到配置项目页面即可,忽略这个警告即可

设置POM位置

这里的POM指的是,项目中的POM位置

在这里插入图片描述

在这里插入图片描述

测试构建

在这里插入图片描述

在这里插入图片描述

构建&手动运行Jar包

构建

在这里插入图片描述

查看Jar包

在这里插入图片描述

安装JDK

yum install -y java-devel
sudo yum install -y java-11-openjdk-devel

手动运行项目

java -jar Jenkins-Learning-0.0.1-SNAPSHOT.jar

在这里插入图片描述

验证正常访问项目接口

在这里插入图片描述

自动化发布到服务器

安装插件

在这里插入图片描述

配置SSH服务器(待发布服务的服务器)

在这里插入图片描述

任务中配置SSH以及构建后操作

在这里插入图片描述

Transfer Set Source files

源文件路径

由构建日志可以得出构建后的Jar的存储目录

Remove prefix

去生成的远端目录中忽略源文件目录的哪些目录

Remote directory

保存的远端地址

Exec command

构建完成后执行的命令

Jar包保存位置

在这里插入图片描述

构建完成后执行的命令

nohup java -jar /root/jenkins/workspace/Jenkins-Learning*.jar &

查看构建结果

日志输出

在这里插入图片描述

查看项目是否启动

ps aux | grep java

在这里插入图片描述

SSH puslishers超时机制

命令优化

控制台执行下面命令的时候会卡顿

nohup java -jar /root/jenkins/workspace/Jenkins-Learning*.jar &

优化为

nohup java -jar /root/jenkins/workspace/Jenkins-Learning*.jar >mylog.log 2>&1 &
该命令可被替换为
nohup java -jar /root/jenkins/workspace/Jenkins-Learning*.jar &>mylog.log &
>覆盖写入
>>追加写入
2代表 标准错误输出
1代表 标准输出
2>&1 将正常输出和错误输出全部写入

替换配置

在这里插入图片描述

配置超时时间

在这里插入图片描述

构建前执行的命令

清理之前打包的Jar包、Kill正在执行的Jar包之类的操作

Pre Steps

编写shell脚本,批量执行操作

  • vi getPidAndKillShell.sh

    • #!/bin/bash
      echo "">/root/getPidAndKillShell.txt
      
  • 修改权限

    • chmod 777 getPidAndKillShell.sh
      
  • 添加配置

    • 在这里插入图片描述
  • 测试构建项目看能否正常执行脚本生成getPidAndKillShell.txt

构建前脚本开发

清理Jar包和杀死进程

修改getPidAndKillShell.sh内容

#!/bin/bash

# 删除历史数据
rm -rf jenkins

# 筛选正在执行的Jar包信息 并取出第二个字符(PID)
pid=`ps -ef | grep Jenkins-Learning | grep 'java -jar' | awk '{printf $2}'`    

# 杀掉当前Jar包进程
kill -9 $pid

增加逻辑判断和参数传入

没找到PID时不进行KILL

#!/bin/bash

appname=$1

# 删除历史数据
rm -rf jenkins

# 筛选正在执行的Jar包信息 并取出第二个字符(PID)
pid=`ps -ef | grep $appname | grep 'java -jar' | awk '{printf $2}'`    

# 如果PID为空(使用-z做空值判断),提示一下,否则执行KILL命令
if [ -z $pid ];
		then
			echo "$appname not start"
		else
			# 杀掉当前Jar包进程
			kill -9 $pid
			echo "$appname stoping......"
fi

运行./getPidAndKillShell.sh Jenkins-Learning

验证未有Jar包运行时

在这里插入图片描述

验证有Jar包运行时

在这里插入图片描述

优化脚本

#!/bin/bash

appname=$1

# 检查是否提供了应用名称参数
if [ -z "$appname" ]; then
    echo "Error: Application name is required."
    exit 1
fi

# 删除历史数据
rm -rf jenkins

# 筛选正在执行的Jar包信息 并取出第二个字符(PID)
pid=$(ps -ef | grep "$appname" | grep 'java -jar' | awk '{print $2}')

# 如果PID为空(使用-z做空值判断),提示一下,否则执行KILL命令
if [ -z "$pid" ]; then
    echo "$appname not start"
else
    # 杀掉当前Jar包进程
    kill -9 $pid
    echo "$appname stopping......"
    
    check=$(ps -ef | grep -w "$pid" | grep java)
    if [ -z "$check" ]; then
        echo "$appname pid:$pid is stopped"
    else
        echo "$appname stop failed"
    fi
fi

测试

在这里插入图片描述

Pre Steps增加参数

在这里插入图片描述

提交代码测试

旧版本

在这里插入图片描述

提交新版本代码

在这里插入图片描述

在这里插入图片描述

运行Jenkins

在这里插入图片描述

发现问题

在这里插入图片描述

两个Jar包都过来了

分析原因,Post Step进行源文件匹配时,匹配到了这两个文件,所以都传过来了

删除jenkins工作目录中旧的jar包

在这里插入图片描述

修改Pre Steps配置的脚本

getPidAndKillShell.sh

#!/bin/bash

appname=$1

# 检查是否提供了应用名称参数
if [ -z "$appname" ]; then
    echo "Error: Application name is required."
    exit 1
fi

# 筛选正在执行的Jar包信息 并取出第二个字符(PID)
pid=$(ps -ef | grep "$appname" | grep 'java -jar' | awk '{print $2}')

# 如果PID为空(使用-z做空值判断),提示一下,否则执行KILL命令
if [ -z "$pid" ]; then
    echo "$appname not start"
else
    # 杀掉当前Jar包进程
    kill -9 $pid
    echo "$appname stopping......"
    
    check=$(ps -ef | grep -w "$pid" | grep java)
    if [ -z "$check" ]; then
        echo "$appname pid:$pid is stopped"
    else
        echo "$appname stop failed"
    fi
fi

# 删除历史数据工作路径数据
rm -rf /root/.jenkins/workspace/learning-jenkins-demo-01/target/Jenkins-Learning*.jar

修改Post Steps配置

修改前

在这里插入图片描述

修改后

在这里插入图片描述

创建postStepsShell脚本
#!/bin/bash

# 找到最新的JAR包
latest_jar=$(ls -t /root/jenkins/workspace/Jenkins-Learning*.jar | head -n 1)

nohup java -jar "$latest_jar"  mylog.log 2>&1 &

重新测试

目前正在运行版本号为03

现在新增加了04版本

在这里插入图片描述

在这里插入图片描述

使用Pipeline

安装插件

pipeline插件和SSH Pipeline Steps插件

在这里插入图片描述

创建流水线

创建任务

在这里插入图片描述

配置Pipeline

在这里插入图片描述

创建Pipeline脚本

pipeline {
    agent any

    environment {
        WORKSPACE_DIR = "/root/.jenkins/workspace"
        TARGET_DIR = "/root/jenkins/workspace"
        JAR_NAME = ""
        APP_NAME = "Jenkins-Learning"
        REPO_URL = "https://github.com/ChenJiahao0205/Jenkins-Learning.git"
        JENKINS_TASK_NAME = "learning-jenkins-demo-02-pipeline"
    }
    
    // 定义 Maven 工具,确保它在 Jenkins 全局工具配置中已定义
    tools {
        maven "maven-3.9.8"
    }

    stages {
        stage('Checkout') {
            steps {
                script {
                    // 从 Git 仓库检出代码
                    checkout([$class: 'GitSCM',
                        branches: [[name: '*/master']], // 替换为你的分支名
                        userRemoteConfigs: [[url: "${REPO_URL}"]]
                    ])
                }
            }
        }

        stage('Clean History Jar') {
            steps {
                script {
                    // 删除历史数据工作路径数据
                    sh "rm -rf ${WORKSPACE_DIR}/${JENKINS_TASK_NAME}/target/Jenkins-Learning*.jar"
                }
            }
        }

        stage('Build') {
            steps {
                script {
                    // 使用 Maven 构建项目
                    sh 'mvn clean package'
                }
            }
        }

        stage('Find Latest Jar') {
            steps {
                script {
                    // 获取最新的 Jar 包名称
                    JAR_NAME = sh(script: "ls -t ${WORKSPACE_DIR}/${JENKINS_TASK_NAME}/target/*.jar | head -n 1", returnStdout: true).trim()
                    echo "Latest Jar: ${JAR_NAME}"
                }
            }
        }

        stage('Move Jar to Target Directory') {
            steps {
                script {
                    // 将最新的 Jar 包移动到目标目录
                    sh "mv ${JAR_NAME} ${TARGET_DIR}/"
                    echo "Moved Jar to Target Directory: ${TARGET_DIR}"
                    
                    // 使用 SSH 将最新的 Jar 包传输到目标服务器
                    // sshPublisher(publishers: [sshPublisherDesc(configName: 'my-server', 
                    // transfers: [sshTransfer(sourceFiles: "${JAR_NAME}", remoteDirectory: "${TARGET_DIR}")],
                    // usePromotionTimestamp: false, alwaysPublishFromMaster: true, paramPublish: true, failOnError: true)])
                }
            }
        }

        stage('Stop Running Application') {
            steps {
                script {
                    // 停止正在运行的 Jar 包
                    sh '''
                    pid=$(ps -ef | grep "${APP_NAME}" | grep 'java -jar' | awk '{print $2}')
                    
                    if [ -z "$pid" ]; then
                        echo "${APP_NAME} not start"
                    else
                        kill -9 $pid
                        echo "${APP_NAME} stopping......"
                        
                        check=$(ps -ef | grep -w "$pid" | grep java)
                        if [ -z "$check" ]; then
                            echo "${APP_NAME} pid:$pid is stopped"
                        else
                            echo "${APP_NAME} stop failed"
                        fi
                    fi
                    '''
                }
            }
        }

        stage('Deploy Application') {
            steps {
                script {
                    // 获取 JAR 文件的名称
                    def jarName = sh(script: "basename ${JAR_NAME}", returnStdout: true).trim()
                    // 启动新的 Jar 包
                    sh "nohup java -jar ${TARGET_DIR}/${jarName} > ${TARGET_DIR}/mylog.log 2>&1 &"
                    echo "Started Application with Jar: ${TARGET_DIR}/${jarName}"
                }
            }
        }
    }

    post {
        always {
            echo 'Pipeline completed.'
        }
        success {
            echo 'Deployment succeeded.'
        }
        failure {
            echo 'Deployment failed.'
        }
    }
}

脚本解释
  • Agent Any: 表示此 Pipeline 可以在任何可用的 Jenkins agent 上运行。

  • Environment: 定义了一些环境变量,比如工作目录和目标目录。

  • tools

    • maven:配置使用maven,在全局工具配置,maven安装中进行配置
  • Stages: 定义了多个阶段。

    • Clean History Jar: 清理历史Jar包
    • Build: 构建项目,使用 Maven 作为示例。如果你的项目不是使用 Maven 构建的,请根据实际情况修改。
    • Find Latest Jar: 使用 shell 命令查找生成的最新 Jar 包。
    • Move Jar to Target Directory: 模拟使用 sshPublisher 插件将最新的 Jar 包传输到目标服务器。这里使用MV代替了
    • Stop Running Application: 停止正在运行的Jar包
    • Deploy Application: 在目标服务器上通过 SSH 执行部署命令,启动 Jar 包。
    • Post Steps: 在 Pipeline 结束后执行的步骤。
  • Always: 无论 Pipeline 成功或失败,总是会执行这一步。

  • Success: 只有当 Pipeline 成功时,才会执行。

  • Failure: 只有当 Pipeline 失败时,才会执行。

执行流水线

报错

Started by user chenjiahao
org.jenkinsci.plugins.scriptsecurity.scripts.UnapprovedUsageException: script not yet approved for use
	at org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.using(ScriptApproval.java:668)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition.create(CpsFlowDefinition.java:123)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition.create(CpsFlowDefinition.java:69)
	at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:312)
	at hudson.model.ResourceController.execute(ResourceController.java:101)
	at hudson.model.Executor.run(Executor.java:442)
Finished: FAILURE

解决方案

在这里插入图片描述

批准脚本运行即可

再次执行流水线

在这里插入图片描述

Java项目无法正常运行

现象

流水线虽然执行成功了,但是程序没有成功启动

通过查看jps发现,程序启动了一瞬间就结束了

[root@jh-centos7 workspace]# jps
8823 war
9945 Jps
[root@jh-centos7 workspace]# jps
8823 war
9979 Jenkins-Learning-0.0.4-SNAPSHOT.jar
9966 Jps
[root@jh-centos7 workspace]# jps
8823 war
9979 -- process information unavailable
9997 Jps

查看日志

发现执行的命令是

nohup java -jar /root/jenkins/workspace/Jenkins-Learning-0.0.4-SNAPSHOT.jar

而非配置中的

"nohup java -jar ${TARGET_DIR}/${jarName} > ${TARGET_DIR}/mylog.log 2>&1 &"

解决:在Pipeline中需要额外配置

参考文章

https://blog.csdn.net/weixin_43767360/article/details/131980955

替换执行Java程序的命令为

JENKINS_NODE_COOKIE=dontKillMe nohup java -jar ${TARGET_DIR}/${jarName} > ${TARGET_DIR}/mylog.log 2>&1 &

最终版Pipeline

pipeline {
    agent any

    environment {
        WORKSPACE_DIR = "/root/.jenkins/workspace"
        TARGET_DIR = "/root/jenkins/workspace"
        JAR_NAME = ""
        APP_NAME = "Jenkins-Learning"
        REPO_URL = "https://github.com/ChenJiahao0205/Jenkins-Learning.git"
        JENKINS_TASK_NAME = "learning-jenkins-demo-02-pipeline"
    }
    
    // 定义 Maven 工具,确保它在 Jenkins 全局工具配置中已定义
    tools {
        maven "maven-3.9.8"
    }

    stages {
        stage('Checkout') {
            steps {
                script {
                    // 从 Git 仓库检出代码
                    checkout([$class: 'GitSCM',
                        branches: [[name: '*/master']], // 替换为你的分支名
                        userRemoteConfigs: [[url: "${REPO_URL}"]]
                    ])
                }
            }
        }

        stage('Clean History Jar') {
            steps {
                script {
                    // 删除历史数据工作路径数据
                    sh "rm -rf ${WORKSPACE_DIR}/${JENKINS_TASK_NAME}/target/Jenkins-Learning*.jar"
                }
            }
        }

        stage('Build') {
            steps {
                script {
                    // 使用 Maven 构建项目
                    sh 'mvn clean package'
                }
            }
        }

        stage('Find Latest Jar') {
            steps {
                script {
                    // 获取最新的 Jar 包名称
                    JAR_NAME = sh(script: "ls -t ${WORKSPACE_DIR}/${JENKINS_TASK_NAME}/target/*.jar | head -n 1", returnStdout: true).trim()
                    echo "Latest Jar: ${JAR_NAME}"
                }
            }
        }

        stage('Move Jar to Target Directory') {
            steps {
                script {
                    // 将最新的 Jar 包移动到目标目录
                    sh "mv ${JAR_NAME} ${TARGET_DIR}/"
                    echo "Moved Jar to Target Directory: ${TARGET_DIR}"
                    
                    // 使用 SSH 将最新的 Jar 包传输到目标服务器
                    // sshPublisher(publishers: [sshPublisherDesc(configName: 'my-server', 
                    // transfers: [sshTransfer(sourceFiles: "${JAR_NAME}", remoteDirectory: "${TARGET_DIR}")],
                    // usePromotionTimestamp: false, alwaysPublishFromMaster: true, paramPublish: true, failOnError: true)])
                }
            }
        }

        stage('Stop Running Application') {
            steps {
                script {
                    // Define variables
                    def pid = sh(script: "pgrep -f 'java -jar ${TARGET_DIR}/${APP_NAME}'", returnStdout: true).trim()
        
                    // Check if the PID exists
                    if (pid) {
                        echo "${APP_NAME} is running with PID: $pid. Stopping it..."
                        sh "kill -9 $pid"
        
                        // Verify if the application has stopped
                        def check = sh(script: "ps -p $pid", returnStatus: true)
                        if (check != 0) {
                            echo "${APP_NAME} pid:$pid has stopped successfully."
                        } else {
                            echo "${APP_NAME} stop failed. Process with PID $pid is still running."
                        }
                    } else {
                        echo "${APP_NAME} is not running."
                    }
                }
            }
        }


        stage('Deploy Application') {
            steps {
                script {
                    // 获取 JAR 文件的名称
                    def jarName = sh(script: "basename ${JAR_NAME}", returnStdout: true).trim()
                    // 启动新的 Jar 包
                    sh "JENKINS_NODE_COOKIE=dontKillMe nohup java -jar ${TARGET_DIR}/${jarName} > ${TARGET_DIR}/mylog.log 2>&1 &"
                        
                    echo "Started Application with Jar: ${TARGET_DIR}/${jarName}"
                }
            }
        }
    }

    post {
        always {
            echo 'Pipeline completed.'
        }
        success {
            echo 'Deployment succeeded.'
        }
        failure {
            echo 'Deployment failed.'
        }
    }
}

脚本解释

  • Agent Any: 表示此 Pipeline 可以在任何可用的 Jenkins agent 上运行。

  • Environment: 定义了一些环境变量,比如工作目录和目标目录。

  • tools

    • maven:配置使用maven,在全局工具配置,maven安装中进行配置
  • Stages: 定义了多个阶段。

    • Clean History Jar: 清理历史Jar包
    • Build: 构建项目,使用 Maven 作为示例。如果你的项目不是使用 Maven 构建的,请根据实际情况修改。
    • Find Latest Jar: 使用 shell 命令查找生成的最新 Jar 包。
    • Move Jar to Target Directory: 模拟使用 sshPublisher 插件将最新的 Jar 包传输到目标服务器。这里使用MV代替了
    • Stop Running Application: 停止正在运行的Jar包
    • Deploy Application: 在目标服务器上通过 SSH 执行部署命令,启动 Jar 包。
    • Post Steps: 在 Pipeline 结束后执行的步骤。
  • Always: 无论 Pipeline 成功或失败,总是会执行这一步。

  • Success: 只有当 Pipeline 成功时,才会执行。

  • Failure: 只有当 Pipeline 失败时,才会执行。

本文示例项目地址

https://github.com/ChenJiahao0205/Jenkins-Learning.git

最后

本文部分内容结合B站视频学习总结得到,参考视频:https://www.bilibili.com/video/BV1bS4y1471A

感谢大家看到这里,文章如有不足,欢迎大家指出;彦祖点个赞吧彦祖点个赞吧彦祖点个赞吧,欢迎关注程序员五条!

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五条Programmer

比心~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值