1. 什么是Jenkins
1.1 一句话定义
Jenkins 是一个开源的自动化构建服务器,把原本手工执行的流程固化成一条流水线,由服务器自动执行,每次结果一致。
它属于持续集成(CI)/ 持续交付(CD)工具这一类。
1.2 手动打包与Jenkins打包
通俗理解Jenkins是做什么的,可以先对比看下,在软件开发与程序打包中,没有 Jenkins 时,一次固件或版本的发布大概是这样:
- 打开编译服务器拉取最新代码手工编译打压缩包拷到共享盘通知相关人员
这种流程可能会存在一些问题:
- 环境不一致:在这个机器上打的包是好的,换个人或换台机器就编不过板子追溯困难:不知道某次出的包对应哪个 commit,比如只能翻聊天记录或核对打包时的打包环境占用人力:打包、拷贝、通知这些零碎活儿每次都要人来做
Jenkins 把这一整串变成:
- 开发者 push代码到Git 仓库webhook 通知或定时轮询,Jenkins 自动执行也可手动触发Jenkins 打包Jenkins的自动流程是:
-
- 拉取代码编译构建打包归档产物通知构建结果与构建产物的位置
1.3 Jenkins中的一些概念
| 概念 | 通俗解释 |
|---|---|
| Job / 任务 | 一个具体的构建任务,比如"某项目主分支编译" |
| Pipeline / 流水线 | 用代码(Jenkinsfile)描述的整条流程 |
| Controller | Jenkins 主服务,负责网页界面、调度、记录结果 |
| Agent / Node | 真正执行编译的机器,可以有多台,各自装不同工具链 |
| Workspace / 工作区 | 每次构建时 Jenkins 自己克隆代码的目录 |
| Trigger / 触发器 | 决定什么时候自动启动,如 push 触发、定时触发 |
| Artifact / 产物 | 构建输出中需要保留的文件,如可执行文件、固件包 |
| Plugin / 插件 | 功能扩展,Jenkins 几乎所有能力都靠插件 |
2. 安装 Jenkins
这里使用Ubuntu20
2.1 安装 JDK 与基础工具
sudo apt update
sudo apt install -y fontconfig openjdk-17-jre git cmake g++ make
验证:
java -version
cmake --version
g++ --version
2.2 添加官方软件源并安装 Jenkins
# 导入仓库签名密钥(文件名以官网当前为准)
sudo mkdir -p /etc/apt/keyrings
sudo wget -O /etc/apt/keyrings/jenkins-keyring.asc
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
# 添加 stable 源
echo "deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/"
| sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt update
sudo apt install -y jenkins
这个 apt update 报错了,查看是有密钥文件的,应该是过期了,Jenkins 的仓库签名密钥每 3 年更换一次
修复方法:只换文件内容,不用改 sources.list
sudo curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2026.key
-o /etc/apt/keyrings/jenkins-keyring.asc
sudo gpg --show-keys /etc/apt/keyrings/jenkins-keyring.asc
再次update,这次是另一个错:
Could not handshake
-
- 表示 TLS 连接失败,属于网络问题
no longer has a Release file
- 只是连带结果:这次没有获取到 Release 文件,apt 就认为该源中没有这个文件
另外注意我这个机器上同时配了两个 Docker 源:
mirrors.aliyun.com/docker-ce/linux/ubuntu |
Hit: 正常 |
|---|---|
download.docker.com/linux/ubuntu |
Err: 连不上 |
保留一个即可:
grep -rn "download.docker.com" /etc/apt/sources.list /etc/apt/sources.list.d/
# 找到是哪个文件(通常是 /etc/apt/sources.list.d/docker.list),把它移走
sudo mv /etc/apt/sources.list.d/docker.list ~/docker.list.bak
sudo apt update
这里显示网络很慢(53.8 MB 下了一小时)
2.3 启动服务与获取初始密码
sudo systemctl daemon-reload
sudo systemctl enable --now jenkins
sudo systemctl status jenkins # 需要能看到 active (running)
我这里又报错了:
目前装的jenkins是 2.580.2。官方 Java 支持政策是:
| Java | 支持的 LTS 范围 | 状态 |
|---|---|---|
| Java 25 | 2.541.1(2026-01)起 | 支持到 2029-09 |
| Java 21 | 2.479.1(2024-10)起 | 支持到 2027-09 |
| Java 17 | 2.346.1 ~ 2.541.3 | 2026-03 已停止 |
修复方法:装 Java 21
curl -fL -o /tmp/temurin21.tar.gz
https://mirrors.tuna.tsinghua.edu.cn/Adoptium/21/jre/x64/linux/OpenJDK21U-jre_x64_linux_hotspot_21.0.13_9.tar.gz
sudo mkdir -p /opt/temurin21
sudo tar xzf /tmp/temurin21.tar.gz -C /opt/temurin21 --strip-components=1
/opt/temurin21/bin/java -version # 应输出 21.0.13
让 Jenkins 用上它
sudo systemctl edit jenkins
编辑器里填入,保存退出:
[Service]
Environment="JAVA_HOME=/opt/temurin21"
然后重启:
sudo systemctl daemon-reload
sudo systemctl restart jenkins
sudo systemctl status jenkins
按q可以退出,这里记录下常用按键:
| 按键 | 作用 |
|---|---|
q |
退出,回到 shell |
空格 / PgDn |
下一屏 |
b |
上一屏 |
↑↓ |
逐行滚动 |
G / g |
跳到末尾 / 开头 |
/关键字 再按 n |
搜索、跳下一个 |
拿到初始管理员密码:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
这是一次性解锁密码,用完后就作废了
xxpcb@xxpcb-ubuntu20:~/Desktop$ sudo cat /var/lib/jenkins/secrets/initialAdminPassword
1e1e6101bbbf4391b42d82fec3c71a06
2.4 首次登录
浏览器打开 http://<服务器IP>:8080(本机就是 http://localhost:8080)。
粘贴上一步的密码 → 点「继续」。
选择 安装推荐的插件(Install suggested plugins)。网络慢的话等几分钟
创建第一个管理员用户(用户名/密码/邮箱),这一套是以后登录用的账号,与上面的初始密码无关。
确认保存之后,会进入下面的界面
2.5 补装必需插件
右上角设置图标,点进去后是下面这个界面,然后点Plugins
然后在Available plugins可以搜索插件进行安装
搜索并安装:
| 插件 | 作用 |
|---|---|
| Git plugin | 从 Git 仓库拉代码(通常已含) |
| Pipeline | 支持 Jenkinsfile 流水线(通常已含) |
| Timestamper | 给控制台输出加时间戳(通常已含) |
| Git Parameter | 构建时下拉选择分支 / tag / commit |
| AnsiColor | 让编译器的彩色告警在控制台正常显示 |
装完勾选:安装完成后重启 Jenkins
3. C++ 项目Jenkins构建示例
3.1 准备一个测试用的Git仓库
Jenkins 需要一个仓库地址拉代码,比如可以在gitee上创建一个仓库:
代码结构如下:
hello_cpp_test_jenkins/
├── CMakeLists.txt
├── build.sh # 本地手动编译脚本,和 Jenkins 里执行的内容一致
├── Jenkinsfile # 后面要用到的 Pipeline 脚本
├── .gitignore
└── src/
└── main.cpp
3.2 本地先验证能编译
在配置 Jenkins 之前,可以先手动编译一下,确认代码没有问题:
3.3 配置Jenkins:Freestyle Job方式
本篇先使用Freestyle Job方式,后面再介绍流水线的方式。
在Jenkins首页新建任务(New Item), 输入项目名称,选择Freestyle project
然后填git地址,比如我的
https://gitee.com/xxpcb/hello_cpp_test_jenkins
Triggers可以不用填,Environment中的Add timestamps to Console Output可以勾选上
构建步骤(Build Steps),Execute shell,粘贴:
set -e
# 打出本次构建的标识,写进二进制便于追溯
BUILD_TAG_INFO="$(git rev-parse --abbrev-ref HEAD)@$(git rev-parse --short HEAD)-build${BUILD_NUMBER}"
echo"构建标识: ${BUILD_TAG_INFO}"
# 编译
rm -rf build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_INFO="${BUILD_TAG_INFO}"
cmake --build build -j$(nproc)
# 冒烟测试(注意不能用 ctest --test-dir,那是 CMake 3.20+ 才有的参数)
cd build && ctest --output-on-failure; cd"$WORKSPACE"
# 打包
VERSION="$(git rev-parse --short HEAD)-b${BUILD_NUMBER}"
mkdir -p out
cp build/hello out/
tar -czf "out/hello-cpp-${VERSION}.tar.gz" -C out hello
ls -lh out/
增加构建后操作步骤(Post-build Actions),归档成品(Archive the artifacts),填:
out/*.tar.gz
保存之后就可以构建了。
3.4 执行Jenkins构建
点击Build Now就可以构建了,下图是已经构建一次后的了
hello-cpp-2b3b142-b1.tar.gz就是构建产物了,名字中:
- 短 commit:能精确定位到代码状态构建号:区分同一个 commit 的多次构建
在Console Output中,可以看到到构建的log打印
3.5 Jenkins的编译位置
从构建的log打印可以看到一个地址:
/var/lib/jenkins/workspace/hello-cpp
可以进到这个目录查看下内容:
这里就涉及三处代码:
本地开发代码目录:自己电脑上的项目代码,Jenkins 从不进入,也不会修改
远端仓库:比如gitee仓库的代码,Jenkins 只读,从不推送
工作区:Jenkins 自己的临时目录,路径是 $JENKINS_HOME/workspace/<任务名>,本例即 /var/lib/jenkins/workspace/hello-cpp。
4 总结
本篇介绍了是什么是Jenkins,以及如何在Ubuntu20上搭建Jenkins,并通过简单的C++项目例子,演示Jenkins自动编译打包的操作过程。
21