Jenkins自动化构建部署Java、Web前后端项目(炒鸡炒鸡详细!少走很多坑)~
本文主要讲解了如何安装Jenkins,以及使用Jenkins自动化构建部署Java、Web项目,避免踩坑!
前言
- 本文以
SpringBoot
项目进行演示。。。- 使用前和使用后对比:
- 以前的打包流程:
本地修改代码->提交Git仓库->等待发布时->拉取代码->在本地使用Maven打成Jar包->先把服务器的jar包停止启动->将本地jar包上传上去->启动新jar包
,总共大致8个步骤。- 使用
Jenkins(CI/CD)
后:本地修改代码->提交Git仓库->打开
Jenkins页面->选择流水线并执行
,总共大致4个步骤- 从上面步骤对比来看,使用能大大提高我们的打包速度,并且减少了很多错误发生的可能。我们只需要前提配置一下流水线步骤,后面只要点击执行按钮,就会按照配置好的步骤自动的一步一步的执行
- 目前也有一些大公司提供了
CI/CD
的工具,但一般免费的都会有总共执行时长的限制。所以我们需要使用开源的Jenkins
来搭建属于我们自己公司的CI/CD
工具
前置准备
共需提前把如下步骤准备好
- 两台服务器,一台启动
Jenkins
服务器,一台用于部署所有应用的服务器。也可以都在同一个服务器中。下面演示基于两台服务器演示- 应用服务器需要安装
JRE 或 JDK
,启动Jar
包Jenkins
服务器共需要安装JDK(Jenkins、Maven需要)、Maven(编译代码打包)、Git(仓库拉取代码)
- 创建一个基本的
SpringBoot
项目,编写一个简单的接口,并提交到Git
仓库,后面基于这个项目演示
1、更新yum
源
- 如果在国内,默认的镜像源地址一般是无法访问的,需要配置为国内其他大厂公开的镜像源地址即可正常使用
yum install
安装
# 备份原配置
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
# 下载新的 repo 文件
# 阿里云镜像源
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# 或清华大学镜像源
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.tuna.tsinghua.edu.cn/help/centos/
# 清除缓存并生成新缓存
sudo yum clean all
sudo yum makecache
2、安装JDK(8或11)
- 如果
Jenkins
是单独安装一个服务器的话,那么建议先查询最新版Jenkins
支持的JDK
版本,然后安装- 如果
Jenkins
和代码都放在同一个服务器,并且最新版Jenkins
所需JDK
版本和代码所需版本一致,那么更好,省去后面jenkins
初始化下载插件的问题了
# 镜像源仓库目前只有8和11的,可以使用 yum search java|grep jdk查看
# 如果部署服务器用到8,或者11,可以使用如下命令快速安装
# 安装Java 8
sudo yum install -y java-1.8.0-openjdk-devel
# 或安装Java 11
#sudo yum install -y java-11-openjdk-devel
# 最后使用java -version查看
卸载JDK
为了防止上面安装错误,这里提供下使用
yum
命令卸载JDK的方式
# 注意修改包名为上面安装的名称
yum remove java-xxx-openjdk-devel
# 查询其他原装的java包
rpm -qa | grep java
# 根据查询出来的包,删除,自行替换版本名称
yum remove -y java-xxx-openjdk*
# 最后再执行如下命令查看是否还有残留
java -version
3、安装高版本JDK
3.1、官网下载
- 高版本JDK可以在官网下载压缩包,然后上传到服务器解压,我这里安装最新版
Jenkins
所需版本:JDK17
,下面安装Jenkins
会教你怎么查看所需JDK
版本- Java Downloads | Oracle,找到对应
Linux
的JDK版本安装
3.2、上传服务器
3.3、解压
# 创建解压后的目录
mkdir /usr/local/java
tar -zxvf jdk-17.0.15_linux-x64_bin.tar.gz -C /usr/local/java
3.4、配置环境变量
# 编辑配置文件(根据 Shell 类型选择,如 ~/.bashrc 或 ~/.zshrc)
vi ~/.bashrc
# 添加内容(需根据实际安装路径修改)
export JAVA_HOME=/usr/local/java/jdk-17.0.15
export PATH=$JAVA_HOME/bin:$PATH
# 使配置生效
source ~/.bashrc
# 验证
java -version
4、安装Maven
4.1、下载Maven
# 安装到opt目录
cd /opt
# 安装支持机器上的JDK版本的即可,我这里支持JDK8的即可
sudo wget https://archive.apache.org/dist/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz
# 将下好的文件解压
sudo tar xzvf apache-maven-3.8.1-bin.tar.gz
# 修改下文件夹名称
sudo mv apache-maven-3.8.1 maven
# 最后执行命令验证
/opt/maven/bin/mvn -v
4.2、配置conf
目录中的Settings.xml
文件的镜像源
sudo vi /opt/maven/conf/settings.xml
在
<mirrors>
标签内添加阿里云镜像,本地仓库地址可配可不配,默认为/path/to/local/repo
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
5、安装Git
sudo yum install -y git
# 验证
git --version
6、关闭防火墙
- 为了演示方便,我这里两个服务器都关闭防火墙,根据实际情况
# 永久关闭开机自启
sudo systemctl disable firewalld
# 关闭防火墙
sudo systemctl stop firewalld
Jenkins下载安装并启动
- 官网:Jenkins
- 前提
- 机器要求:
- 256 MB 内存,建议大于 512 MB
- 10 GB 的硬盘空间(用于 Jenkins 和 Docker 镜像)
- 需要安装以下软件:
- Java ( JRE 或者 JDK 都可以,具体版本根据下载的
Jenkins
所需版本安装)- 下面,我将会使用
VMware+CentOS 7
演示下载并安装
1、下载
2、将war
包放入服务器中
3、启动war
包
- app.log
作用:将标准输出(STDOUT,编号 1)重定向到 app.log 文件。
效果:Jenkins 的正常运行日志会写入 app.log。- 2>&1
作用:将标准错误(STDERR,编号 2)重定向到与标准输出相同的目标(即 app.log)。
效果:错误日志和正常日志会合并到同一个文件。- &
作用:将命令放入后台执行,让出当前终端控制权。
效果:命令执行后不会阻塞终端,可继续输入其他命令。
nohup java -jar jenkins.war --httpPort=8080 > app.log 2>&1 &
Jenkins
页面介绍
- 上面操作完成后,我们页面访问
服务器ip+:8080
即可访问Jenkins
页面了- 刚进页面会显示一行英文字母,在初始化,等耐心等待一会即可
1、进入页面
1.1、账号和密码
- 跳转页面后,会显示管理员密码存放在哪个目录中,执行命令即可查看
- 或者打开启动日志,最底下也会输出初始密码
cat /root/.jenkins/secrets/initialAdminPassword
1.2、初始化
- 进入后,会让我们选择插件的初始化安装,我们这里选安装推荐的插件即可,然后会帮我们安装如下插件,耐心等待全部安装完成
- 如果很多个插件安装报错,可以使用
cat app.log
查看日志,是否是插件所需的Jenkins
版本不够(安装老版本可能会出现),那么就需要取消安装所有插件,然后去官网下载插件,在Jenkins
页面中一个一个上传上去,比较麻烦
1.3.创建管理员账号
1.4、实例配置
自动生成,一般不用改
2、配置全局工具
进入页面后,点击左侧
系统管理
->右侧全局工具配置
,配置我们的JDK
和Maven
地址,后面配置流水线会用到
JAVA配置如下,别名随意
Maven配置如下,名称随意
使用Maven插件创建任务(SSH启动)
- 下面我们演示的流水线执行步骤:
拉取代码->通过Maven插件编译打包->停止并删除部署服务器的jar包->将Jar包发送到部署服务器->通过java -jar命令启动
- 前提准备:
- 1个部署项目的服务器(需要有
Docker
)- 一个
Git
仓库,用于将代码提交上去,我这里使用公共的Gitee
用来演示- 共需要执行如下几步
- 安装
Maven Integration
(使用Maven创建任务)、Publish Over SSH
(远程连接其他服务器发送文件或执行命令等操作)插件- 创建
Item
并选择使用Maven
创建- 填写创建表单
- 配置拉取代码的
Git
仓库地址- 配置
Maven
要执行的命令- 将编译完成的
jar
包发送到部署的服务器
中- 在部署的服务器中编写脚本
1、安装插件
1.1、安装Maven Integration
左侧
系统管理
->右侧插件管理
->左侧Available plugins
(可用插件)搜索:Maven Integration
然后左侧勾选后,右上角点击安装
在跳转的页面最下面,即可看到安装状态
完成后点击下面返回首页即可
1.2、安装Publish Over SSH
插件
- 其余步骤同上,就搜索内容不一样
- 下载完成后,我们需要去配置里面,配一下需要用到的服务器
- 左侧
系统管理
->右侧系统配置
,然后找到SSH Servers
配置(一般在最下面)
2、新建任务
左侧
新建任务
输入任务名称,并选择
构建一个Maven项目
(这个选项是安装上面插件后自动出现的)
3、编辑任务配置(重要)
- 这一步我们将配置主要的步骤流程
- 共有如下几个重要步骤
- 配置
Git
仓库地址- 配置
Maven
执行命令编译打包- 设置打完包后的步骤(连接部署服务器,发送
jar
包,启动jar
包)
3.1、配置Git
仓库地址
- 我这里使用的是公共仓库,没有账号密码。有需要可以点击
添加
3.2、配置Maven
命令
- 这里执行
clean package -DskipTests
命令即可够用
3.3、配置发布步骤
这个是配置在
Post Steps
中,Add post-build step
中选择我们添加的SSH
插件提供的功能Send file or execute commands over SSH
然后配置如下,执行的命令:
nohup java -jar apps/MySpringBoot-0.0.1-SNAPSHOT.jar > app.log 2>&1 &
配置完成后,我们点击最下方按钮
save
即可
3.4、验证
3.4.1、Web页面验证
点击按钮返回后,我们点击左侧菜单
立即构建
,就可以执行了,然后下面会显示新任务构建的进度条
点击下方的构建任务,然后再点击左侧菜单的
控制台输出
,可以看到构建的每一步日志情况,最下面会展示执行结果
3.4.2、服务器验证
- 连接部署服务器,然后进入
/root/apps
目录,查看是否有jar
包- 并且执行
jps
命令,查看是否启动服务了
3.4.3、服务验证
最后,访问我们代码的测试接口,查看是否正常访问
4、问题
- 上面虽然成功了,但是当你重新修改代码->提交->页面执行任务->访问接口,你会发现不生效了
- 原因:虽然文件传输成功了,会把之前的
jar
包替换掉,但是之前jar
包启动的服务还在运行,后面的启动只会无效,并不会顶替,那么我们在上传文件前,要先把原来启动的服务停掉,最好jar
包也删掉- 但是问题又来了,每次启动的
jar
包的进程ID
都不一样,即jps
查询的ID
不一样,那么我们肯定是不能写死了,怎么解决呢?
- 我们可以提前在部署服务器上编写一个脚本,将所有复杂的命令写进去,我们在网页只需要配置执行这个脚本即可,那么脚本我在第五节会提供
5、解决问题
5.1、脚本
- 脚本会比较复杂,我尽量注释写的详细点,大家一部分一部分粘贴上去可以先手动执行下看看效果
- 因为我们上面设置的部署服务器是基于
/root
目录操作的,所以我下面内容放到/root/auto-start-jar.sh
中- 执行命令
./auto-start-jar.sh MySpringBoot
,后面参数换成项目服务名即可通用
#!/bin/bash
# 打印传入脚本的参数,并且用appname名称接收
appname="$1"
echo "arg: $appname"
# 判断脚本参数是否有值
if [ -z "$appname" ];
then
# 如果没有输入内容,那么打印内容,并退出,返回报错码1
echo "params [serviceName] is not null"
exit 1
fi
# 先删除历史 jar 包
rm -rf "apps/${appname}"*.jar
# 获取指定项目正在运行的jar包pid
pid=$(ps -ef | grep "[j]ava -jar .*$appname" | awk '{print $2}')
# 打印下获取的值
echo "检测到 PID: $pid"
# 如果pid为空,提示一下,否则,执行kill命令
# -z代表zero,即0,无值即代表0,表示 if($pid = 0)
if [ -z "$pid" ];
then
# 如果无值,那么打印 xxxx 没有启动
echo "$appname not started"
else
# 否则kill掉
kill -9 "$pid"
# 并且打印提示语
echo "$appname stoping......"
# 最后使用fi表示结束
fi
5.2、修改任务
注意:是在
Pre Steps
中新增步骤,原来在Post Step
中的不动
选中任务,点击左侧配置
翻到最下面
Pre Steps
中,添加文件传送前的操作步骤(执行上面sh
脚本)
文件和命令表单,只要填一个就可以
然后保存后,修改代码,提交,重新执行,等待执行我查看接口结果即可
6、优化:Docker外挂运行
安装
Docker
我就不写步骤了,可以参考Docker-初级安装及使用-CSDN博客具体流程图如下
缺点:这种只能针对单个固定Jar文件名称的
jar
文件挂载,配置比较局限步骤如下:
- 部署服务器先安装Docker
- 然后拉取JDK17的镜像
Jenkins
配置启动容器命令即可
6.1、Docker服务器拉取镜像
# 我这边代码是17版本写的,所以拉取17的,其他版本修改版本号即可
docker pull openjdk:17
6.2、准备启动命令
- 可以自己先把
jar
包上传到服务器的/root/apps
目录中,然后执行命令尝试
docker run -d -p 8888:8888 --name my-spring-boot -v /root/apps/MySpringBoot-0.0.1-SNAPSHOT.jar:/app.jar openjdk:17 java -jar app.jar
6.3、Jenkins
页面添加SSH连接
- 因为我是新加了一个服务器放Docker的,所以有这一步,如果还是用上面的服务器,那么则无需
系统管理->系统配置->SSH Servers
6.4、编辑/新建任务
直接修改上面的
job1
或者新增一个job2
都可以要修改的点如下,注意:这里可以先在部署服务器上创建好容器,然后页面上
Pre
就可以先停止容器docker stop xxxx
,Post
再启动容器即可docker start xxxx
,这就外挂的好处,可以更简单点,我这里演示并无需提前创建
Pre Steps
先删除文件、停掉并且删除之前的容器
Post Steps
传送文件,并执行启动命令6.2小节有
最后保存,并且执行,查看结果即可
7、再优化:Docker内部运行
- 这里根据
Dockerfile
,将代码打包到镜像中,创建容器直接执行即可Dockerfile
要放在代码中,然后在Jenkins
把代码中的Dockerfile
发送到部署服务器中,然后去build
文件即可- 这样其他服务就可以共用这一个任务,只需要修改拉取代码的地址即可
7.1、代码中编写Dockerfile
- 后面将这个文件发送到部署服务器中
FROM openjdk:17
# 暴露端口
EXPOSE 8888
# 工作目录
WORKDIR /root
# 复制jar包 具体jar包名称根据实际修改
ADD apps/MySpringBoot-*.jar /root/app.jar
# 启动程序
ENTRYPOINT ["java", "-jar", "/root/app.jar"]
7.2、编辑/新建任务
我这里新建一个,其他的配置都跟之前一样,只
Pre 和 Post
即可
Pre
:将代码的Dockerfile
发送到部署服务器中,并且删除之前的jar
包,停止并删除容器、删除镜像
Post
:执行docker build
构建镜像,并创建容器创建任务这里也可以选择其他任务进行修改
7.2.1、Pre
将拉取下来的代码中的
Dockerfile
发送到部署服务器中
命令
rm -rf apps/MySpringBoot-*.jar
docker stop my-spring-boot
docker rm -f my-spring-boot
docker rmi myspringboot:latest
配置
7.2.2、Post
命令
docker build -t myspringboot .
docker run -d -p 8888:8888 --name my-spring-boot myspringboot
配置
7.2.3、测试
- 最后清空部署服务器之前的内容(包括容器(关闭的也要删掉)、
jar
包等)- 然后页面执行后,查看是否实现效果
使用流水线(Pipeline
)创建任务(推荐)
- 官方文档:流水线
- 下面演示其实执行逻辑和上面一样,只是从配置,改为了使用代码配置
- 为什么推荐使用
Pipeline
创建呢,好处如下:
- 可以自定义步骤分组,并且在页面上也能更好地展示出来。如果有报错,会显示到对应的步骤上,方便调试
- 可以从指定的步骤开始执行,跳过之前的步骤
- 流水线可以有选择的停止或等待人工输入或批准,然后才能继续运行流水线。
- 支持复杂的需求等
- 流水线有两种分类,下面演示基于声明式流水线:
- 声明式流水线:基于结构化语法,强制遵循特定格式,适合标准化流程(如 CI/CD 模板),结构清晰、强制规范,适合快速上手和标准化场景。
- 脚本式流水线:基于Groovy 脚本,更灵活自由,适合复杂逻辑(如动态流程、条件判断),灵活强大、适合复杂逻辑,但学习成本较高。
Jenkins
流水线的定义被写在一个文本文件中 (成为Jenkinsfile
),分别可以在Web UI、代码根目录的Jenkinsfile
中编写Pipeline
声明式流水线有几个重要的步骤如下:
pipeline { ... }
:声明式 Pipeline 的顶层容器,所有内容必须包含在pipeline
块内。
- 必选参数:
- 至少包含
agent
和stages
。agent any
:指定 Pipeline 执行的节点(Agent)。
any
:Jenkins 自动选择一个可用的节点。none
:不分配全局 Agent,需为每个stage
单独指定 Agent。- 其他选项:如
agent { label 'docker' }
(指定标签为docker
的节点)。stages { ... }
:包含多个stage
的容器,按顺序执行每个阶段。
- 特点:
- 阶段是逻辑分组,用于组织相关的
steps
(如构建、测试、部署)。- 若某个阶段失败,后续阶段默认不会执行。
stage('名称') { ... }
:定义一个具体的阶段,每个阶段包含多个steps
。steps { ... }
:包含一系列具体的命令或操作,是实际执行工作的地方。
- 支持的操作:
- Shell 脚本(如
sh 'mvn clean package'
)。- Jenkins 内置命令(如
echo 'Hello World'
)。- 插件提供的命令(如
git checkout master
)。- 流水线定义有两种选择(创建流水线后,配置页面
定义
下拉框中选择)
Pipeline script
:在Web页面编写Pipeline
脚本Pipeline script from SCM
:将定义为Jenkinsfile
,并放入代码中。Jenkins
拉取代码后,自动读取里面脚本
1、Web UI
编写脚本
1.1、使用官方写好的演示使用
1.1.1、创建任务,选择流水线
1.1.2、翻到下面选择案例演示
- 这里的定义值为
Pipeline script
代表在下面代码框中编写脚本
1.1.3、保存后,然后点击执行
- 当新建一个
Pipeline
任务首次执行时,可能会报错,说需要管理员审批- 这时候需要管理员点击
系统管理->In Process Script Approval
中审批,审批通过后,再次执行即可成功- 当新建、或修改了语法时,首次执行必须都要经过管理员同意后才可后续执行
1.2、结果页面功能讲解
- 当执行完,并且点击左下角执行的任务时,可以跳转到任务的详情页面。
- 自己查看可以发现和之前使用
Maven
创建的任务是多了几个菜单的,这是Pipeline
模式的专属的信息- 我下面讲解的是一些重要的信息
1.2.1、Console Output
- 这里也和之前一样,显示执行的日志信息,可以查看每一步的日志
1.2.2、Pipeline Overview
- 这里展示
Pipeline
定义的每一步的响应日志信息- 并且可以选择从新运行(
Return
)或者编辑代码并且重新运行这次构建(Replay
)或者选中步骤后,从选中的步骤重新执行后面的步骤(Restart from Stage
)
1.2.3、从指定阶段重新运行
- 不仅从上面页面点击去可以,这个菜单也可以从指定步骤开始运行
1.2.4、回放
- 修改并回放一个构建过的流水线,方便调试
1.2.5、流水线步骤
- 可以查看每行代码的执行状态,方便调试
1.3、流水线语法
其实把之前一些配置,变为代码,我们用到一些插件并不知道怎么写对应的代码。
Jenkins
也给我们提供了生成代码的工具重新配置写好的流水线,翻到最下面,有一个流水线语法的蓝色字,点击文字即可跳转
跳转过后的页面,就是详细介绍流水线使用方式了,我们这里使用左侧的第一个菜单
片段生成器
即可然后在右侧示例步骤中选择我们之前用到的插件,比如
Git、SSH
等配置,填写配置后,点击生成流水线脚本即可。git
仓库有账号密码的话,添加凭据并选择即可
1.4、编写我们之前的业务逻辑
- 编写
Shell
脚本的话,使用sh 'xxxx'
即可。如果是多行的话,就是用三个引号包起来,里面可以换行写sh """ xxx """
- 我这里共分为三个大步骤,和之前的步骤一样
- 拉取代码:拉取Git仓库代码
- 重置环境:发送
Dockerfile
文件,停止并删除容器,删除镜像- 构建代码:
maven
构建- 部署服务:发送
jar
包,重新构建镜像并启动容器- 每次编写完脚本首次执行,如果
Jenkins
版本和我的一样是2.5.xx
以上的,基本都会报错,需要管理员审批。同意后再次执行即可成功
1.4.1、Pipeline
脚本
pipeline {
agent any
tools {
// 引用Jenkins全局工具配置中定义的Maven(名称需与配置一致)
maven 'maven3.9' // 对应Jenkins全局工具配置中的Maven名称,大小写敏感
}
// 所有步骤放这里面
stages {
// 定义每个步骤
stage('拉取代码') {
// 步骤内的逻辑
steps {
// 使用流水线语法生成
git 'https://gitee.com/tianchencheng/test-jenkins.git'
// 打印日志
echo '--------------代码拉取成功!--------------'
}
}
stage('重置环境') {
steps {
// 需要使用流水线语法生成
sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf apps/MySpringBoot-*.jar
docker stop my-spring-boot
docker rm -f my-spring-boot
docker rmi myspringboot:latest''',
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '--------------环境重置完成!--------------'
}
}
stage('构建代码') {
steps {
sh 'mvn clean package -DskipTests'
echo '--------------构建完成!--------------'
}
}
stage('部署服务') {
steps {
// 需要使用流水线语法生成
sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t myspringboot .
docker run -d -p 8888:8888 --name my-spring-boot myspringboot''',
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'apps', remoteDirectorySDF: false, removePrefix: 'target/', sourceFiles: 'target/MySpringBoot*.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '--------------服务部署完成!--------------'
}
}
}
}
1.4.2、Console Output
执行结果
1.4.3、Pipeline Overview
效果
1.5、其他配置
1.5.1、状态菜单展示执行流程及结果
- 点击
Pipeline
的状态菜单,可以发现有点空旷,我们可以将Stages
里面内容也添加到这里,省得再去点击Stages
菜单了- 我们可以在
系统管理->Appearance
菜单勾选:
Show pipeline graph on job page
:在作业页面上显示管道图Show pipeline graph on build page
:在构建页面上显示流水线图- 效果如下
任务页面
任务详情页面
构建时的详情页面
1.6、小总结
- 通过上面演示,我们可以很快的排查到出错的步骤,并且可以清晰的看到每一步的执行时间及结果
Pipeline
大部分的配置我们都可以使用片段生成器
工具生成,剩余一些简单的sh
等命令,编写一下即可完成,其实总的来说并不难理解Jenkins
新版的Pipeine
是有权限审批的,每次创建以及编辑Pipeline
代码后,首次执行一定会报错,需要管理员账号去系统管理->In Process Script Approval
页面中点击审批通过即可
2、Jenkinsfile
编写脚本
- 与上面的区别就是将
Pipeline
代码放入服务代码的Jenkinsfile
中
- 优点:
- 单分支下,只需修改代码中的
Jenkinsfile
文件即可实现修改任务执行逻辑- 在多分支情况下,只需修改分支代码中的
Jenkinsfile
配置,以及修改任务中的Git
拉取分支,即可实现不同分支执行不同的任务,比如mster
分支编写打包生产的Jenkinsfile
,测试分支编写打包测试的Jenkinsfile
,执行不同分支的打包时,只需要手动修改任务配置的拉取分支即可- 在代码写脚本时,配合
IDEA
的插件,可以获得很好的语法提示- 因为是跟随代码提交到仓库,有文件的历史记录,可以追踪
- 缺点:
- 想要将
master
分支打包测试环境就需要修改代码的Jenkinsfile
文件- 新建分支时,要注意拷贝分支的
Jenkinsfile
满不满足新分支打包需求,否则需要修改,避免打错地方- 打不同分支包需要先修改
Jenkinsfile
中拉取代码的分支配置(可以通过下面章节的多分支流水线
功能优化,动态选择分支执行任务)- 修改代码中的
Jenkinsfile
,无需管理员账户审批,,无权限管理,可能导致有人恶意修改脚本后执行- 这里建议单分支情况下可以使用如下演示的内容。如果多分支,建议只学习使用
Jenkinsfile
,具体如何搭配任务使用,建议看完下一章节多分支流水线
再决定如何配置- 我下面只使用单分支进行演示
2.1、代码创建Jenkinsfile
文件
记得创建完成提交代码
pipeline {
agent any
tools {
// 引用Jenkins全局工具配置中定义的Maven(名称需与配置一致)
maven 'maven3.9' // 对应Jenkins全局工具配置中的Maven名称,大小写敏感
}
// 所有步骤放这里面
stages {
// 定义每个步骤
stage('Jenkinsfile 拉取代码') {
// 步骤内的逻辑
steps {
// 使用流水线语法生成
git 'https://gitee.com/tianchencheng/test-jenkins.git'
// 打印日志
echo '--------------代码拉取成功!--------------'
}
}
stage('Jenkinsfile 重置环境') {
steps {
// 需要使用流水线语法生成
sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf apps/MySpringBoot-*.jar
docker stop my-spring-boot
docker rm -f my-spring-boot
docker rmi myspringboot:latest''',
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '--------------环境重置完成!--------------'
}
}
stage('Jenkinsfile 构建代码') {
steps {
sh 'mvn clean package -DskipTests'
echo '--------------构建完成!--------------'
}
}
stage('Jenkinsfile 部署服务') {
steps {
// 需要使用流水线语法生成
sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t myspringboot .
docker run -d -p 8888:8888 --name my-spring-boot myspringboot''',
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'apps', remoteDirectorySDF: false, removePrefix: 'target/', sourceFiles: 'target/MySpringBoot*.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '--------------服务部署完成!--------------'
}
}
}
}
2.2、新建Pipeline
任务
在
定义
下拉框中选择Pipeline script from SCM
,并且配置git
仓库配置,上面的配置根据需要勾选(下面演示无需勾选)
2.3、测试
上面配置完成保存返回即可,然后点击左侧
立即构建
即可
多分支流水线(推荐的推荐)
- 实际开发中,我们肯定不止一个测试分支,可能会
test-02-23、test-03-25
等,后面加上创建分支的时间,在新分支里面添加改动代码。新分支测试没问题了再合并到主测试分支这样- 那么我们不可能每个分支编写一套任务,最好在一个任务中,能有下拉框让我们选择对应打包的分支最好,这样我们可以指定某个分支执行同一个任务了
- 多分支流水线配置可以分为两种:
- 不同分支执行相同流水线:就是在执行同一个流水线的时候选择不同的分支执行
- 不同分支执行不同流水线:在一个任务中,按分支分组分为多个子任务,生产分支根据生产代码配置走生产的流水线,测试根据测试代码配置走测试的流水线
- 下面我这里演示一下怎么配置出来这个分支选择框
1、不同分支执行相同流水线
1.1、方法一(简单/手动配置分支)
如下方法有一个缺点:当代码添加/修改分支名后,对应的任务也要编辑配置的下拉选项
1.1.1、准备
- 首先我们肯定要有两个分支,并且内容不一致,方便区分验证
1.1.2、编辑Pipeline->General
- 我们还是使用上面创建的
Pipeline
进行演示,编辑任务配置,然后勾选参数化构建过程
,点击添加参数->选项参数
,然后定义参数名称、配置下拉框选项即可- 注意:第一个即为默认选项,尽量填写测试分支名称,避免误按
1.1.3、编辑Pipeline->流水线
代码
- 这里我们要使用到上面定义的参数,可以使用
"${params.参数名}"
来获取,放到git
的配置中
git branch: "${params.branch}", url: 'https://gitee.com/tianchencheng/test-jenkins.git'
1.1.4、保存并验证
- 保存后,进入到任务页面,然后左侧菜单
Build with Parameters
,在页面选择要打包的分支点击Build
即可开始
1.2、方法二(利用插件自动获取分支)
首先,我们要先去
系统管理->插件管理->安装Git Parameter
插件安装完成后,我这里再新建一个任务,复制
Pipeline-1
来修改(任务新建页面下面可以输入要复制的任务),只需输入新任务名称即可删除原来
参数化构建过程
里面的配置,重新添加参数,选择Git 参数
表单内容根据我下面红框内填写即可
修改
Piepine
代码,上面定义的变量使用"${params.branch}"
来获取
保存后,点击左侧
Build whth Params
菜单,可以看到右侧有红色字体,无需理会,直接选择分支后点击Build
,当然,可能你需要管理员账户审核通过,才能正常执行
构建完毕后,我们再次点击
Build whth Params
菜单,注意观察下拉框里面,会出现加载loading
,这是正在拉取Git
仓库的分支信息,当你新增和删除分支后,重新刷新这个页面,分支也会动态更新最后你可以新增分支后,刷新页面进行测试!!!
优化:你也可以在配置的时候,不输入默认分支,然后下面高级里面勾选
Required Parameter
必选,这样每次构建的时候,必须选择分支了,否则点击Build
会报错
2、不同分支执行不同流水线
该配置,适用于基本每个分支都有自己单独的流水线配置,都不相同,执行页面如下
每次扫描到新分支时,会默认执行一次。
当新增/修改/删除分支时,需要手动点击左侧
立刻扫描 多分支流水线
即可刷新页面分支。第一次扫描完后,后续如果修改代码中的Jenkinsfile
,则无需再扫描,也可以在任务的配置页面配置定时刷新
2.1、准备
首先要有两个服务器,一个生产服务器部署
master
分支,一个测试服务器test
分支,记得在系统管理->系统配置->SSH Servers
配置服务器
代码创建两个分支,并且分别在根目录创建
Jenkinsfile
文件,并且修改文件内容
test分支:拉取test分支的代码、构建步骤标题可以添加
test分支
等信息区分、远程操作的服务器修改为test
服务器pipeline { agent any tools { // 引用Jenkins全局工具配置中定义的Maven(名称需与配置一致) maven 'maven3.9' // 对应Jenkins全局工具配置中的Maven名称,大小写敏感 } // 所有步骤放这里面 stages { // 定义每个步骤 stage('Jenkinsfile test分支 拉取代码') { // 步骤内的逻辑 steps { // 使用流水线语法生成 git branch: 'test', url: 'https://gitee.com/tianchencheng/test-jenkins.git' // 打印日志 echo '--------------代码拉取成功!--------------' } } stage('Jenkinsfile test分支 重置环境') { steps { // 需要使用流水线语法生成 sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer-test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf apps/MySpringBoot-*.jar docker stop my-spring-boot docker rm -f my-spring-boot docker rmi myspringboot:latest''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) echo '--------------环境重置完成!--------------' } } stage('Jenkinsfile test分支 构建代码') { steps { sh 'mvn clean package -DskipTests' echo '--------------构建完成!--------------' } } stage('Jenkinsfile test分支 部署服务') { steps { // 需要使用流水线语法生成 sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer-test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t myspringboot . docker run -d -p 8888:8888 --name my-spring-boot myspringboot''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'apps', remoteDirectorySDF: false, removePrefix: 'target/', sourceFiles: 'target/MySpringBoot*.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) echo '--------------服务部署完成!--------------' } } } }
master分支:拉取master分支的代码、构建步骤标题可以添加
master分支
等信息区分、远程操作的服务器修改为prd
服务器pipeline { agent any tools { // 引用Jenkins全局工具配置中定义的Maven(名称需与配置一致) maven 'maven3.9' // 对应Jenkins全局工具配置中的Maven名称,大小写敏感 } // 所有步骤放这里面 stages { // 定义每个步骤 stage('Jenkinsfile master分支 拉取代码') { // 步骤内的逻辑 steps { // 使用流水线语法生成 git 'https://gitee.com/tianchencheng/test-jenkins.git' // 打印日志 echo '--------------代码拉取成功!--------------' } } stage('Jenkinsfile master分支 重置环境') { steps { // 需要使用流水线语法生成 sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer-prd', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf apps/MySpringBoot-*.jar docker stop my-spring-boot docker rm -f my-spring-boot docker rmi myspringboot:latest''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) echo '--------------环境重置完成!--------------' } } stage('Jenkinsfile master分支 构建代码') { steps { sh 'mvn clean package -DskipTests' echo '--------------构建完成!--------------' } } stage('Jenkinsfile master分支 部署服务') { steps { // 需要使用流水线语法生成 sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer-prd', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t myspringboot . docker run -d -p 8888:8888 --name my-spring-boot myspringboot''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'apps', remoteDirectorySDF: false, removePrefix: 'target/', sourceFiles: 'target/MySpringBoot*.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) echo '--------------服务部署完成!--------------' } } } }
2.2、创建多分支流水线
创建任务时,勾选
多分支流水线
,任务名称建议为服务名称,一个服务对应多个分支
配置分支源,用于扫描分支和获取
Jenkinsfile
文件
配置
Jenkinsfile
文件所在项目地址
可以配置自动扫描分支的时间间隔,或者手动点击菜单扫描。每次扫描出来新分支,会自动执行一次
下面的
孤儿项策略
可以根据需要配置,其他就不需要修改什么了
配置完成后,就会自动触发扫描多分支流水线,点击左侧的
扫描多分支流水线
即可查看
等待扫描完成后,点击左侧
状态
菜单,即可查看到扫描的分支了,如果是首次扫描出来的分支,在左下角也会看到分支正在执行
点击对应分支右侧的开始按钮,即可执行对应分支的流水线了
可以点击子分支查看任务执行明细
测试结果
构建前端Node项目流水线
- 其余演示的都是构建
Java
后端项目的步骤,其实都大差不差。为了补全前后端,这里也放上前端的打包流程,如果公司需要部署Java
后端、Node
前端项目,参考这篇文档即可- 下面演示使用
Docker
安装Nginx
部署前端项目- 大致步骤:
拉取代码->清除docker的容器、镜像以及文件->npm/pnpm安装项目依赖构建项目->将构建好的文件以及Dockerfile发送到目标服务器,并构建并运行镜像
,其实和部署java
项目差不多,只不过构建工具从maven
换为node
了- 技术栈:
vite:4.x、Vue:3.x、node:16.x、pnpm:9.6.1、
- 指定
vite
版本安装(否则最新版不支持node16.x
):pnpm create vite@4
1、准备
1.1、创建项目以及Git仓库
使用
vite
创建v3
项目:开始 | Vite 官方中文文档,我这里演示的正式但稍微复杂点,点击按钮调用之前后端写的那个测试接口,将返回值打印在页面上。但是代码我就不写到这了,因为不是重点,相信大家都会搭出来这么一套基本的前后端服务
最后提交
Git
仓库步骤就不演示了,这里我仓库设置私有,就需要在Jenkins
中添加Git
凭据了
CentOS 7
最高只支持node16.x
版本,再高就要升CentOS 8
了。因为7
的glibc默认2.17
版本,但是16+
的node
需要GLIBC_2.27
及以上,而CentOS 8
默认的glibc是2.28
版本,支持的
1.2、代码根目录创建Dockerfile
文件
- 后面我们会把这个文件在
Jenkins
中通过SSH
插件发送到部署服务器中
FROM nginx:1.28.0
# 暴露端口
EXPOSE 80
# 复制jar包
ADD dist/ /usr/share/nginx/html/
# 启动Nginx并保持前台运行
CMD ["nginx", "-g", "daemon off;"]
# 构建命令
# docker build -t my-vue3-web .
# 运行命令
# docker run -d --name my-vue3-web -p 80:80 -v /root/webApps/myVue3Web/nginx-conf/nginx.conf:/etc/nginx/conf.d/default.conf my-vue3-web
1.3、服务器安装node
- 这个
node
要安装到部署Jenkins
的服务器上,我这里安装NVM
用来管理node
版本,不了解nvm
的可以查看Node-包管理工具整套下载使用讲解(nvm、npm、yarn、cnpm、pnpm、nrm)_下载pnpm-CSDN博客- 注意
Linux
系统版本、Node
版本、Vite
版本是有依赖的,我这里CentOS 7 + Node 16 + Vite 4
1.3.1、nvm
安装命令
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
# 激活nvm(重启终端后自动生效)
source ~/.nvm/nvm.sh
# 测试
nvm -v
1.3.2、使用nvm
安装Node
# 安装最新LTS版本
nvm install --lts
# 安装指定版本(如16.20.2)
nvm install 16.20.2
# 切换使用版本
nvm use 16.20.2
# 设置默认版本
nvm alias default 16.20.2
# 最后验证
node -v
npm -v
1.3.3、安装pnpm
- 一般项目使用什么工具,就一直使用这一个工具,否则安装依赖等操作可能会有问题。比如项目搭建初使用的就是
pnpm
,那么所有打包这个项目的电脑,尽量都使用pnpm
,不要在一个项目中,有的使用npm
,有的是用yarn
,有的是pnpm
npm i -g pnpm@8.6.2
# 验证安装
pnpm -v
1.3.4、修改镜像源
- 如果各位觉得执行
install
命令下载依赖很慢,可以执行如下命令切换镜像源
# 查看当前镜像地址
npm config get registry
# 官方镜像:https://registry.npmjs.org/
# 阿里云镜像:https://registry.npmmirror.com/
# 腾讯云镜像:https://mirrors.cloud.tencent.com/npm/
npm config set registry https://registry.npmmirror.com
1.4、服务器创建目录
要现在服务器上创建好我们前台代码编译好的文件,我这里放在
/root/webapps/myVue3Web
目录中,并且要先创建好nginx-conf/nginx.conf
文件,内容如下server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; # 处理Vue路由 location / { try_files $uri $uri/ /index.html; } }
我们有关
myVue3Web
项目的,都会放到这个目录中,包括dist、Dockerfile
文件,目录如下,当然,这里只需要提前创建好nginx-conf/nginx.conf
文件即可,其余的无需提前创建,后面会通过Jenkins
发送过来
1.5、安装Node
插件
Jenkins
搜索安装NodeJS
插件,然后在全局工具
中配置node
地址
如果使用上面
nvm
安装的node
的话,可以使用nvm which current
命令查看node
目录,只复制到版本号那里即可
2、Jenkins
新建任务
下面我们使用
Jenkinsfile
的方式来配置任务,因为我是比较喜欢并且推荐这种方式的创建任务页面依旧选择
流水线
然后配置页面的
定义
下拉框选择Pipeline script from SCM
,然后配置git
仓库地址,以及Jenkinsfile
地址
3、Jenkinsfile
文件
然后就是重中之重,在代码跟路径创建
Jenkinsfile
文件,并且配合代码生成器:http://ip:port/job/web-myVue3Web/pipeline-syntax/
编写出来这么个文件,并且提交Git
仓库
pipeline {
agent any
tools {
nodejs 'node16' // 指定 Jenkins 全局工具配置中的 Node.js 版本
}
stages {
stage('拉取代码') {
steps {
// 使用流水线语法生成
git credentialsId: 'ad68df2e-173e-48dc-9094-64d6a3d08150', url: 'https://gitee.com/tianchencheng/my-vue3-web.git'
echo '--------------代码拉取成功!--------------'
}
}
stage('重置环境') {
steps {
// 需要使用流水线语法生成
sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer-test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand:
'''cd webApps/myVue3Web
rm -rf dist
rm -rf Dockerfile
docker stop my-vue3-web
docker rm -f my-vue3-web
docker rmi my-vue3-web''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '--------------环境重置完成!--------------'
}
}
stage('构建代码') {
steps {
sh """
pnpm install
pnpm build
"""
echo '--------------构建完成!--------------'
}
}
stage('部署服务') {
steps {
// 需要使用流水线语法生成 先发送dist文件,再发送Dockerfile文件,并且执行命令
sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer-test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'webApps/myVue3Web', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'dist/**/*'), sshTransfer(cleanRemote: false, excludes: '', execCommand:
'''cd webApps/myVue3Web
docker build -t my-vue3-web .
docker run -d --name my-vue3-web -p 80:80 -v /root/webApps/myVue3Web/nginx-conf/nginx.conf:/etc/nginx/conf.d/default.conf my-vue3-web''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'webApps/myVue3Web', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '--------------服务部署完成!--------------'
}
}
}
}
4、坑
sshPublisher
的Remote directory
配置的地址,根目录默认是root
(如果系统配置的Remote directory
没填的话)- 并且
Remote directory
配置的地址对下面的Exec command
命令执行所在地址不生效,命令还是在/root
目录中执行,需要先cd xxxxx
目录中- 传输
dist
目录要使用通配符dist/**/*
,不能只写dist
- 最好更换一下
npm
源,否则构建会很慢
5、优化(压缩dist
目录发送至部署服务器)
- 上面是简单版本的,我们直接把
dist
目录内的所有文件,通过通配符dist/**/*
全部传过去- 如果项目比较大,打包以后的文件也会达到
M
级别的的大小。所以可以先压缩,然后将压缩后的文件发送至部署服务器,可以有效增加任务的执行速度- 主要修改的地方:
- 构建完成后,执行
tar -zcvf dist.tar.gz dist
命令压缩- 部署时将压缩后的
dist.tar.gz
文件发送过去,然后使用命令tar -zxvf dist.tar.gz dist && rm -rf dist.tar.gz
解压后再再行docker build
构建镜像- 下面放一下主要的两个步骤的代码
stage('构建代码') {
steps {
sh """
pnpm install
pnpm build
tar -zcvf dist.tar.gz dist
"""
echo '--------------构建完成!--------------'
}
}
stage('部署服务') {
steps {
// 需要使用流水线语法生成
sshPublisher(publishers: [sshPublisherDesc(configName: 'DockerServer-test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'webApps/myVue3Web', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'dist.tar.gz'), sshTransfer(cleanRemote: false, excludes: '', execCommand:
'''cd webApps/myVue3Web
tar -zxvf dist.tar.gz dist && rm -rf dist.tar.gz
docker build -t my-vue3-web .
docker run -d --name my-vue3-web -p 80:80 -v /root/webApps/myVue3Web/nginx-conf/nginx.conf:/etc/nginx/conf.d/default.conf my-vue3-web''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'webApps/myVue3Web', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '--------------服务部署完成!--------------'
}
}
任务触发方式
在任务的配置中,
Triggers
里面可以配置任务的多种触发方式
下面我演示三种常用的
1、其他工程构建后触发
- 这种适合依赖其他服务的情况,比如
Java
中依赖其他模块的代码,被依赖的模块打包后,依赖的服务也都要进行打包(当然,架构要尽量避免这种情况)
2、定时构建
进入任务的配置页面,勾选定时构建
然后在下面的输入框中输入
Cron
表达式,来定义任务根据配置好的执行时间来定时执行
Cron
表达式工具:Crontab.guru - The cron schedule expression generator,翻译一下页面即可
最后修改完配置,等待3分钟查看任务是否自动构建即可
3、触发远程构建(Git
仓库的WebHook
触发)
- 这种可以调用
Jenkins
服务提供的API
,传入对应的参数,即可触发任务的构建功能。- 经常和
Git
仓库的WebHook
功能搭配使用,实现当Git
仓库进行提交、合并
等操作时,自动触发任务的构建- 注意:如果你的
Jenkins
所在服务器是内网环境,那么你必须在内网中搭建一套Git
仓库,比如GitLab
,否则Git
仓库是访问不到你内网服务器IP
的,也就调用不了里面的接口了。也就是说,你的Jenkins 和 Git仓库
要么都处于内网环境,要么都处于外网环境,必须互相能访问到- 如果不会搭建
Git
仓库的可以参考:GitLab搭建与使用(SSH和Docker)两种方式-CSDN博客- 我这里就不演示了,只说步骤
3.1、任务配置页面
进入任务配置页面的
Triggers
中,勾选触发远程构建
,然后填写属于这个任务的Token
生成后的地址大概是:
http://192.168.71.111:8080/buildWithParameters?token=Pipepine-Jenkinsfile
这种然后打开
git
仓库(我这里以Gitee
演示),并且进入项目->管理中,左侧选中WebHook
,然后新增后进行配置
点击
添加
按钮会校验,地址是否能被访问到。如果添加没问题,那么可以提交代码进行测试了。下面是访问不到的情况
4、轮询SCM
(不推荐)
注意:如果不是必须,尽量不要使用。轮询会发送多次无用请求,占用带宽以及服务器资源。可以使用上面那种方式替代。
上面第三节是被动接收
Git
仓库的调用,那么这个就是主动调用仓库,查看是否有更新信息依旧是在
Triggers
中,勾选轮询SCM
,并且填写Cron
表达式
配置完成后,提交代码,然后等待3分钟后查看任务是否有新增构建记录即可
任务执行完成后发送邮件
- 首先要有两个邮箱,一个是发送邮件的邮箱,另外一个是接收邮件的邮箱
- 我这里发送邮件使用
163邮箱
,接收邮箱使用QQ邮箱
演示
1、准备
1.1、163邮箱
官网进入邮箱,并且登录成功后,点击设置,开启
POP3/SMTP服务
服务
开启后,会有弹框,点击继续开启,然后弹框中会有一串授权密码,这个要记下来,否则后面看不到只能重新新增了,后面
Jenkins
会当做密码使用
最后翻到最下面,记一下服务器的
SMTP地址:smtp.163.com
1.2、QQ邮箱
- 官网登录上,等待查看邮件即可
2、配置
2.1、系统配置
2.1.1、Jenkins Location
在
Jenkins
页面中,点击系统管理->系统配置
,然后先找到Jenkins Location
配置,填写内容
2.1.2、Extended E-mail Notification
如果没有这个插件,去插件市场安装即可。这是初始化时,选择官方推荐插件安装的
在这里配置的是全局的一个默认配置,后面每个项目中可以单独使用这个插件去用全局的一个配置值,也可以个性化修改每个项目邮件的内容等信息
然后找到
Extended E-mail Notification
配置,这个配置是个性化,就是可以在任务执行完成、失败后发送的邮件信息配置,这个配置才是重要的
然后再往下翻一点,可以看到
Default Subject
邮件主题,可以使用Jenkins
提供的一些变量,作为邮件的主题使用下面还有配置
Default Recipients
(默认收件人,多个,分割)、Default Subject
(默认主题)Default Content
(默认的邮件内容),这里也可以使用变量,可以自定义内容(这里定义的是全局变量的值)
再往下,有一个**
Default Triggers
按钮**,这个是配置发送邮件的触发条件,这里一般选择如下这三个就够用,根据实际情况选择
Aborted
(终止):如果构建状态为“Aborted”,将发送电子邮件。构建通过 UI 或 API 中止,但通常需要某种用户干预才能发生。中止的构建在执行过程中停止。Always
(总是):始终在构建后触发电子邮件,无论构建的状态如何Before Build
(构建前):在构建开始时,但在 SCM 轮询完成后,将发送电子邮件。Failure - Any
(失败 - 任何):每当构建失败时,都会发送电子邮件。如果配置了“Failure - Still”触发器,并且之前的构建状态为“Failure”,则“Failure - Still”触发器将改为发送电子邮件。Failure - 1st
(失败 - 第 1 次):当构建状态从 “Success” 更改为 “Failure” 时,将发送电子邮件。Failure - 2nd
(失败 - 第 2 次):当构建成功后,如果构建连续两次失败,将发送电子邮件。Failure - Still
:当构建成功后,如果构建连续两次失败,将发送电子邮件。Failure - X
(失败 - X):构建成功后,如果构建连续失败 X 次,将发送电子邮件Failure → Unstable (Test Failures)
(失败 → 不稳定(测试失败)):每当构建从失败(编译或构建步骤失败)变为不稳定(单元测试失败)时,都会发送电子邮件。这基本上意味着所有构建步骤都成功了,但仍有测试失败。Fixed
(固定):当构建状态从 “Failure” 或 “Unstable” 更改为 “Success” 时,将发送电子邮件。Not Built
(未构建):如果构建状态为“未构建”,将发送电子邮件。此状态代码用于多阶段构建(如 maven2),其中早期阶段的问题会阻止后期阶段的构建。Script - After Build
(脚本 - 构建后):允许用户定义执行该脚本以确定是否应在构建发生后发送电子邮件。脚本的最后一行应解析为 true 以发送电子邮件,或 false 以不发送电子邮件。请参阅下面的 Script Trigger Options(脚本触发器选项),了解脚本可用的参数。Script - Before Build
(脚本 - 构建前):允许用户定义一个脚本,该脚本将执行以确定是否应在构建开始之前发送电子邮件。脚本的最后一行应解析为 true 以发送电子邮件,或 false 以不发送电子邮件。请参阅下面的 Script Trigger Options(脚本触发器选项),了解脚本可用的参数。Status Changed
(状态已更改):如果构建状态发生变化,将发送电子邮件。Success
(成功):如果构建状态为 “Successful”,将发送电子邮件。如果配置了“Fixed”触发器,并且之前的构建状态为“Failure”或“Unstable”,则“Fixed”触发器将改为发送电子邮件。Test Improvement
(测试改进):每当有改进时,我们都会发送电子邮件。每当 build 的测试失败次数少于上一个 build 时,即认为该 build 已改进。如果当前失败计数变为 0(不再有测试失败),则此触发器将不会发送电子邮件。Test Regression
(测试回归):每当出现回归时,都会发送电子邮件。每当某个构建的失败次数多于上一个构建,或者有新的测试失败时,该构建就会被视为回归。Unstable (Test Failures)
(不稳定(测试失败)):每当构建不稳定时,都会发送电子邮件。如果存在测试失败,但所有构建步骤都已成功完成,则构建不稳定。如果配置了“Unstable - Still”触发器,并且之前的构建状态为“Unstable”,则“Unstable - Still”触发器将改为发送电子邮件。Unstable (Test Failures) - 1st
(不稳定(测试失败)- 第 1 个):当构建状态从 anything 更改为 “Unstable” 时,将发送电子邮件。Unstable (Test Failures) - Still
(不稳定 (测试失败) - 静止):如果连续两个或多个构建的构建状态为“不稳定”,将发送电子邮件。如果存在测试失败,但所有构建步骤都已成功完成,则构建不稳定。Unstable (Test Failures)/Failure → Success
(不稳定(测试失败)/失败 → 成功):当构建状态从 “Failure” 或 “Unstable” 更改为 “Success” 时,将发送电子邮件。中间的 “Aborted” 构建将被忽略。
上面配置的内容,在后面项目的邮件个性化配置中,可以使用
${XXXX}
去引用全局的配置,只需要点击配置右边的?
即可查看使用什么变量名引用(有一些是没有的,那么大概率如果不配置就会使用系统配置的值,可以自行尝试验证)
2.1.3、邮件通知
这个是系统级别的通知,当发生非常严重级别的才会发送通知,配置如下
然后回到
然后就全部配置完成了,保存并退出页面即可
2.2、自由模式的任务配置
进入到任务->配置页面,翻到最下面,找到
构建设置
,这里只需要配置一下收件人邮箱
然后在下面的
构建后操作
中,增加构建后操作步骤,然后选择Editable Email Notification
,可以个性化配置项目的邮件内容等配置然后找到
Advanced Settings
点击后,再找到Triggers
,设置用户组,然后在失败和成功中都添加Build User
,保证包含构建的用户执行构建操作
保存后,执行构建任务,并查看控制台输出,我这里构建成功,发送的是成功的邮件
2.2.1、构建成功
- 并且使用电脑(因为使用的虚拟机,电脑可以访问虚拟机中的服务器)点击邮件中的地址,可以直接跳转到任务明细的信息页面
2.2.2、构建失败
- 信息只有一行,并且点击跳转失败,后面会优化模板
2.3、Pipeline
模式任务配置
Pipeline
就要在Jenkinsfile
代码中添加配置了下面我们会在
Pipeline
中新增一个属性post
:用于定义构建完成后执行的操作(如发送通知、清理资源)。它支持根据不同的构建状态(成功、失败、始终执行等)执行不同的步骤。以下是详细的写法和示例:pipeline { agent any // 其他部分... post { // 不同状态的后置操作 always { // 始终执行 } success { // 构建成功时执行 } failure { // 构建失败时执行 } unstable { // 构建不稳定(如测试失败)时执行 } aborted { // 构建被手动终止时执行 } } }
然后我们依旧使用
片段生成器
,选择如下插件
然后填写需要的配置
实际要添加的代码如下,
stages
同级下面添加
post {
always {
echo '构建结束...'
// 偷懒写法,其实下面三个状态,定义三遍,值一样
emailext body: '$DEFAULT_CONTENT', postsendScript: '$DEFAULT_POSTSEND_SCRIPT', presendScript: '$DEFAULT_PRESEND_SCRIPT', recipientProviders: [buildUser()], replyTo: '$DEFAULT_REPLYTO', subject: '$DEFAULT_SUBJECT', to: '$DEFAULT_RECIPIENTS'
}
success {
echo '恭喜您,构建成功!!!'
}
failure {
echo '抱歉,构建失败!!!'
}
unstable {
echo '部分失败....'
}
}
3、优化邮件模板
上面使用的是默认的模板,很简陋,并且难以观察表达的内容,可以在全局配置中使用如下模板,进行优化
首先,
Default Content Type
的值要为HTML(text/html)
,Default Subject
值为【构建通知】
然后在
Default Content
中填写如下内容<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"> <tr> 本邮件由系统自动发出,无需回复!<br/> 各位同事,大家好,以下为${PROJECT_NAME }项目构建信息</br> <td><font color="#CC0000">构建结果 - ${BUILD_STATUS}</font></td> </tr> <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> <hr size="2" width="100%" align="center" /></td> </tr> <tr> <td> <ul> <li>项目名称 : ${PROJECT_NAME}</li> <li>项目描述 : ${JOB_DESCRIPTION}</li> <li>构建编号 : 第${BUILD_NUMBER}次构建</li> <li>触发原因: ${CAUSE}</li> <li>构建状态: ${BUILD_STATUS}</li> <li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li> <li>构建 Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li> <li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li> </ul> </td> </tr> <tr> <td><b><font color="#0B610B">变更集</font></b> <hr size="2" width="100%" align="center" /></td> </tr> <td>${JELLY_SCRIPT,template="html"}<br/> <hr size="2" width="100%" align="center" /></td> </tr> </table> </body> </html>
然后就是再项目中配置了,分两种项目
自由项目如下配置
Pipeline
项目配置
3.1、成功效果
3.2、不稳定/失败效果
Jenkins
集群(高级)
Jenkins
集群适合当构建任务比较多,并且同时构建的几率比较大时
Jenkins
的集群不是一个服务放多个服务器上,一个挂掉了,其他的还能用的概念。而是多个服务一起执行构建任务,这个服务执行这个构建任务,另一个服务执行另一个构建任务,实现并行执行不同的任务,互不影响当只有一台
Jenkins
服务,构建任务是串行的,必须一个构建完,才能构建下一个。如果还没构建完,又来了一个构建任务,就回进入构建队列中
这样后面的队列就会一直等一直等,直到前面的都完成了,才该它执行,比较耗时。
集群服务要求:
- 只有主节点服务器需要
Jenkins
服务,其他服务器无需安装Jenkins
服务。集群服务要有主节点服务器执行任务所需要的环境,比如JDK、Maven、Node
,并且版本尽量一致!!!,否则可能会导致构建环境不一致报错配置完集群后,我们需要了解任务配置中的两个概念
- 并发构建:允许当前任务同时有多个节点执行构建,相当于并发操作同一个任务,一般关闭!!!
- 限制项目运行节点:限制当前任务可以在那些节点上构建,如果有需要不同的服务器构建,则勾选填写规则。否则默认由
Jenkins
分配,任意节点都可执行下面我再开两台服务器用来搭建集群,总共三台
1、主节点新增集群配置
点击左侧菜单
系统管理->节点和云管理
可以看到当前只有一个节点
master
然后点击右上角
New Node
新增节点,并且输入节点名称
配置如下,选择工作目录一般不要直接
/root
,可以创个jenkins
单独的文件夹,因为主节点会发一些文件到从节点配置的目录中,供构建使用。避免误删
保存后,可以点击表格中的节点,然后点击左侧
日志
,查看连接情况
等待连接成功表格中会变成如下模样,没有的话可以点击右上角刷新
第三个节点可以复制现有节点,修改标签以及服务器连接配置即可
最后节点页面如下
返回
Dashboard
页面后,查看左下角,也可以发现配置的节点
最后,我们查看集群服务器的
/root
目录下,可以发现Jenkins主节点
自己会给从节点发送文件并且启动jar
包等操作,用于集群使用
2、任务配置
任务配置分为两种分类
使用
Maven
插件创建的任务:需要在任务的配置页面选择是否可以并发构建,或者指定某个节点,并发构建一般关闭!
流水线构建的任务:根据
Jenkinsfile
的agent
值判断
如果为
any
,则由Jenkins
分配,任意节点都可执行如果为对象,那么根据
label
属性值,判断指定某个节点执行agent { label 'jenkins-02 || jenkins-03' // 同时满足多个标签的节点 }
agent none
:不分配全局节点,需每个 stage 单独指定。指定节点可以使用标签表达式
&&、||
等表达式
3、测试
注意:为了方便演示,我这里勾选允许并发限制节点,不在乎任务成功或失败了。所以才能看到下面多个节点同时构建同一个任务。实际不要勾选
3.1、不限制节点
3.2、限制节点
3.2.1、只配置了jenkins-02
3.2.2、配置了jenkins-02 || jenkins-03
总结
通过上面的步骤,可以发现,配置其实并不难,并且一次配置,可以长期使用。只需要点点按钮即可,非常方便
上面的演示只是基于一个服务演示,文件夹建的比较简陋。正常公司一般都会有很多服务,最好
apps目录
下建立对应的服务名文件夹,防止意外执行删除其他服务等操作
Jenkins
执行任务时,会在本地服务所在目录创建一个.jenkins
隐藏文件,所有数据都保留在其中,注意不要误删等操作,使用ls -a
可以查看到
jobs
:里面存放的是所有任务的配置数据
workspace
:里面存放任务执行时的缓存数据,比如从代码仓库拉取下来的文件
建议:
- 建议使用
流水线
构建任务,这样可以可视化的查看任务执行步骤,并且更快定位问题所在步骤。- 构建流水线时,根据需求判断使用
Web UI
方式编写Pipeline
还是使用Jenkinsfile
编写,优缺点章节初有描述,建议使用Jenkinsfile
方式编写- 建议流水线配置邮件发送,这样执行情况可以根据邮件实时观察
- 构建任务多的话,建议使用集群模式,减少任务排队时间
- 执行
sh
脚本时,一定要多多测试,确定命令执行目录地址,确定命令是否可能导致误删等操作注意:由于
Jenkins
任务一般都会执行一些重置环境的指令,比如删除容器、镜像等操作。执行的命令或脚本一定要测试的没问题了再用到正式环境!!!,并且不要搞错Jenkins
任务中命令执行所在的目录地址。必要时可以一条一条命令的配置,然后执行,查看是否按照预期执行
其他功能及配置演示
1、IDEA Jenkins
插件
1.1、安装
打开
IDEA
,搜索并安装Jenkins Control
插件
1.2、配置
1.2.1、生成API Token
我们需要先去
Jenkins
页面中生成一个tokne
,在登录插件需要用到
点击左侧
系统管理->管理用户
点击用户右侧下拉列表的
Security
右侧
API Token
中,点击添加新Token
按钮,并输入token
名称后,生成
一定要保存这个
Token
,后续就无法查看了。除非重新生成
1.2.2、IDEA插件配置
IDEA
插件安装完成后,IDEA
软件右侧菜单会有一个Jenkins
的菜单,点击后,然后点击三个点再点击Jenkins Server Settings
然后填写表单内容,并点击
TEST CONNECTION
,进行连接测试。最后点击OK
保存并退出配置弹框
然后右侧
Jenkins
菜单就有我们的任务列表了,一切操作都在菜单中执行
1.3、使用
1.3.1、构建
选中任务,双击或者右击
Build on Jenkins
即可开始构建
1.3.2、查看日志
右侧选中任务,点击上面按钮即可查询当前任务的日志
右键下面任务信息,然后点击
Show Log
即可在下面查看当前执行情况的日志
2、优化Vite
项目打包日志
当你创建了一个
Vite
项目的任务时,查看日志会发现,当执行pnpm build
时,日志会有乱码信息,这是因为这些输出是Linux
终端中带有 ANSI 颜色代码和控制字符 的日志,用于美化输出(如颜色、加粗、下划线等)。在终端中会正常显示为带颜色的文本,但直接复制到文本文件或 Jenkins 控制台时会显示为类似[...m
的乱码。
2.1、解决方法
Jenkins
安装插件AnsiColor
Pipeline
中,使用pnpm build
的脚本时,外面包上ansiColor('xterm') {sh '...'}
stage('构建代码') { steps { ansiColor('xterm') { // 启用 ANSI 颜色解析 sh """ pnpm install pnpm build tar -zcvf dist.tar.gz dist """ // 执行带颜色输出的命令 } echo '--------------构建完成!--------------' } }
2.2、重新构建查看日志
插件使用以及坑
sshPublisher
插件
1、Remote directory
有全局配置和项目配置
2、连接不上SSH
服务器,最终结果是UNSTABLE
而不是FAILURE
3、Remote directory
配置只针对发送文件生效,对执行命令所在目录不生效
即便系统配置中
Publish over SSH
服务器配置了Remote directory
为/root/aaa
,但是Exec command
的命令执行目录还是/root
下图中,虽然
Remote directory
是apps
,也会把MySpringBoot*.jar
文件放入这个目录中,但是下面执行Exec command
的目录所在地依旧是/root
。想要修改目录只能先执行cd xxxx
,再执行命令
Maven
插件
1、Pipelie
中使用需要先在tools
中定义,并且要和全局配置的名称一致
NodeJS
插件
1、Pipelie
中使用需要先在tools
中定义,并且要和全局配置的名称一致
更多推荐
所有评论(0)