26人参与 • 2026-04-26 • Linux
jenkins 是一个开源的自动化服务器,它可以帮助我们实现:
相比 gitlab ci、github actions、circleci 等工具,jenkins 在企业私有化部署、复杂流水线控制、权限管理方面具有明显优势。
官方网站:https://www.jenkins.io
我们假设你有一台运行 ubuntu 22.04 lts 或 centos stream 9 的服务器。以下操作均基于命令行完成。
# ubuntu sudo apt update && sudo apt upgrade -y # centos sudo dnf update -y
jenkins 推荐使用 openjdk 11 或 17:
# ubuntu 安装 openjdk 17 sudo apt install openjdk-17-jdk -y # centos 安装 openjdk 17 sudo dnf install java-17-openjdk-devel -y # 验证安装 java -version
你应该看到类似输出:
openjdk version "17.0.9" 2023-10-17 openjdk runtime environment (build 17.0.9+8-ubuntu-122.04) openjdk 64-bit server vm (build 17.0.9+8-ubuntu-122.04, mixed mode, sharing)
# 导入 gpg key curl -fssl https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \ /usr/share/keyrings/jenkins-keyring.asc > /dev/null # 添加仓库源(ubuntu) echo deb [signed-by=/usr/share/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
如果你是 centos 用户,请访问官方文档获取对应安装方式。
sudo apt install jenkins -y
sudo systemctl start jenkins sudo systemctl enable jenkins sudo systemctl status jenkins
你应该看到 active (running) 表示服务正常运行。
# ubuntu 使用 ufw sudo ufw allow 8080 # centos 使用 firewalld sudo firewall-cmd --permanent --add-port=8080/tcp sudo firewall-cmd --reload
sudo cat /var/lib/jenkins/secrets/initialadminpassword
复制输出的密码,稍后用于首次登录。
打开浏览器,访问:
http://<your-server-ip>:8080
输入刚才获取的初始密码,进入插件安装界面。
推荐选择 “install suggested plugins” —— 这会自动安装常用插件,包括 git、maven、pipeline、ssh 等。
安装完成后,创建第一个管理员用户:
然后设置 jenkins url(默认即可),点击 “save and finish”。
恭喜!jenkins 已成功安装并初始化!
进入 manage jenkins → plugins → available plugins
搜索并安装以下插件:
安装后重启 jenkins:
sudo systemctl restart jenkins
为了演示自动化部署,我们先创建一个简单的 spring boot 项目。
mkdir -p ~/jenkins-demo-app cd ~/jenkins-demo-app
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation="http://maven.apache.org/pom/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelversion>4.0.0</modelversion>
<groupid>com.example</groupid>
<artifactid>jenkins-demo-app</artifactid>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>3.1.5</version>
<relativepath/>
</parent>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceencoding>utf-8</project.build.sourceencoding>
</properties>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-test</artifactid>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-maven-plugin</artifactid>
<configuration>
<mainclass>com.example.jenkinsdemoappapplication</mainclass>
<finalname>${project.artifactid}-${project.version}</finalname>
</configuration>
</plugin>
</plugins>
</build>
</project>src/main/java/com/example/jenkinsdemoappapplication.java
package com.example;
import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.restcontroller;
@springbootapplication
@restcontroller
public class jenkinsdemoappapplication {
public static void main(string[] args) {
springapplication.run(jenkinsdemoappapplication.class, args);
}
@getmapping("/health")
public string healthcheck() {
return "✅ jenkins demo app is running! version: " + getclass().getpackage().getimplementationversion();
}
@getmapping("/info")
public appinfo getappinfo() {
return new appinfo("jenkins demo app", "1.0.0", system.getproperty("java.version"));
}
static class appinfo {
private final string name;
private final string version;
private final string javaversion;
public appinfo(string name, string version, string javaversion) {
this.name = name;
this.version = version;
this.javaversion = javaversion;
}
// getters(省略 setter,保持不可变)
public string getname() { return name; }
public string getversion() { return version; }
public string getjavaversion() { return javaversion; }
}
}src/test/java/com/example/jenkinsdemoappapplicationtests.java
package com.example;
import org.junit.jupiter.api.test;
import org.springframework.boot.test.context.springboottest;
import org.springframework.boot.test.web.client.testresttemplate;
import org.springframework.boot.test.web.server.localserverport;
import org.springframework.http.responseentity;
import static org.assertj.core.api.assertions.assertthat;
@springboottest(webenvironment = springboottest.webenvironment.random_port)
class jenkinsdemoappapplicationtests {
@localserverport
private int port;
private final testresttemplate resttemplate = new testresttemplate();
@test
void contextloads() {
// 测试应用是否能正常启动
}
@test
void healthendpointreturnsok() {
responseentity<string> response = resttemplate.getforentity(
"http://localhost:" + port + "/health", string.class);
assertthat(response.getstatuscode().is2xxsuccessful()).istrue();
assertthat(response.getbody()).contains("running");
}
@test
void infoendpointreturnsjson() {
responseentity<string> response = resttemplate.getforentity(
"http://localhost:" + port + "/info", string.class);
assertthat(response.getstatuscode().is2xxsuccessful()).istrue();
assertthat(response.getbody()).contains("name");
assertthat(response.getbody()).contains("version");
}
}在项目根目录执行:
mvn clean package
如果一切顺利,你会在 target/ 目录下看到生成的 jar 文件:
target/jenkins-demo-app-1.0.0.jar
运行它:
java -jar target/jenkins-demo-app-1.0.0.jar
访问 http://localhost:8080/health 应该返回健康状态信息。
虽然我们不提供 github 地址,但你可以将项目推送到任意支持 git 的代码托管平台(如 gitlab、gitee、bitbucket 等)。
git init git add . git commit -m "initial commit: jenkins demo app" git remote add origin <your-git-repo-url> git push -u origin main
确保 jenkins 服务器可以访问该仓库(如果是私有仓库,需配置凭据)。
点击 new item → 输入名称 jenkins-demo-app → 选择 freestyle project → 点击 ok。
在 source code management 中选择 git:
https://your-git-server.com/your-group/jenkins-demo-app.git勾选 build periodically,填写:
h */2 * * * # 每两小时构建一次
或勾选 poll scm:
h/5 * * * * # 每5分钟检查一次代码变更
勾选 add timestamps to the console output(方便查看日志时间)
点击 add build step → 选择 invoke top-level maven targets
clean package点击 add post-build action → archive the artifacts
target/*.jar再添加一个 → publish junit test result report
**/target/surefire-reports/test-*.xml进入 manage jenkins → configure system
滚动到 publish over ssh 区域:
/var/lib/jenkins/.ssh/id_rsa(推荐使用密钥认证)在 ssh servers 下点击 add
prod-serveryour-production-server-ipdeploy/home/deploy/apps点击 test configuration,应显示 “success”。
提示:确保目标服务器上已创建 deploy 用户,并赋予相应目录写入权限。
在目标服务器(生产机)上创建部署脚本:
# 登录生产服务器 ssh deploy@your-production-server-ip # 创建部署目录 mkdir -p /home/deploy/apps/scripts mkdir -p /home/deploy/apps/logs # 创建部署脚本 nano /home/deploy/apps/scripts/deploy.sh
脚本内容如下:
#!/bin/bash
app_name="jenkins-demo-app"
version=$1
jar_file="$app_name-$version.jar"
app_dir="/home/deploy/apps"
log_dir="$app_dir/logs"
pid_file="$app_dir/app.pid"
# 创建日志目录
mkdir -p $log_dir
# 停止旧进程
if [ -f "$pid_file" ]; then
pid=$(cat $pid_file)
if ps -p $pid > /dev/null; then
echo "stopping existing process $pid..."
kill $pid
sleep 5
if ps -p $pid > /dev/null; then
kill -9 $pid
echo "force killed process $pid"
fi
fi
rm -f $pid_file
fi
# 启动新应用
echo "starting $jar_file..."
nohup java -jar $app_dir/$jar_file \
--server.port=8081 \
> $log_dir/app.log 2>&1 &
# 保存新进程id
echo $! > $pid_file
echo "application started with pid $(cat $pid_file)"
sleep 3
# 检查是否启动成功
if ps -p $(cat $pid_file) > /dev/null; then
echo "✅ deployment successful!"
exit 0
else
echo "❌ deployment failed!"
exit 1
fi赋予执行权限:
chmod +x /home/deploy/apps/scripts/deploy.sh
回到 jenkins 项目配置页面,在 构建后操作 中添加:
send build artifacts over ssh
prod-servertarget/jenkins-demo-app-*.jartarget//home/deploy/appscd /home/deploy/apps version=$(echo jenkins-demo-app-*.jar | sed 's/jenkins-demo-app-\(.*\)\.jar/\1/') chmod +x scripts/deploy.sh ./scripts/deploy.sh $version
保存配置。
点击 build now,观察控制台输出。
如果一切顺利,你应该看到:
访问生产服务器上的应用:
http://<production-server-ip>:8081/health
应该看到:
✅ jenkins demo app is running! version: 1.0.0
自动化部署成功!
下面是一个典型的 jenkins 自动化部署流程图:

这个流程涵盖了从代码提交到生产部署的全过程,确保每次部署都是可追踪、可验证、可回滚的。
虽然自由风格项目易于上手,但在复杂场景下,pipeline 更具优势:
在项目根目录创建 jenkinsfile:
pipeline {
agent any
tools {
maven 'maven 3.8.6'
jdk 'openjdk 17'
}
environment {
app_name = 'jenkins-demo-app'
server_ip = 'your-production-server-ip'
deploy_user = 'deploy'
artifact_dir = 'target'
}
stages {
stage('checkout') {
steps {
checkout scm
script {
env.build_version = sh(script: 'echo ${pom_version}', returnstdout: true).trim()
}
echo "building version: ${env.build_version}"
}
}
stage('build') {
steps {
sh 'mvn clean package -dskiptests'
}
}
stage('test') {
steps {
sh 'mvn test'
}
post {
always {
junit '**/target/surefire-reports/test-*.xml'
}
}
}
stage('deploy to production') {
when {
branch 'main'
}
steps {
sshpublisher(
publishers: [
sshpublisherdesc(
configname: 'prod-server',
transfers: [
sshtransfer(
sourcefiles: "${artifact_dir}/${app_name}-${build_version}.jar",
removeprefix: "${artifact_dir}/",
remotedirectory: "/home/deploy/apps"
)
],
usepromotiontimestamp: false,
useworkspaceinpromotion: false,
verbose: true
)
]
)
// 执行远程部署脚本
sshcommand(
remote: 'prod-server',
command: """
cd /home/deploy/apps
version=\$(echo ${app_name}-*.jar | sed 's/${app_name}-\\(.*\\)\\.jar/\\1/')
chmod +x scripts/deploy.sh
./scripts/deploy.sh \$version
"""
)
}
}
}
post {
success {
echo '✅ build and deployment completed successfully!'
// 可添加邮件、slack、钉钉等通知
}
failure {
echo '❌ build or deployment failed!'
// 发送告警通知
}
}
}jenkinsfilepipeline 将自动读取 jenkinsfile 并执行定义的流程。
真实项目通常需要多个环境:
我们可以扩展 pipeline 支持多环境:

对应的 jenkinsfile 片段:
stage('deploy') {
when {
anyof {
branch 'develop'
branch 'main'
branch 'release/*'
}
}
steps {
script {
def targetenv = ""
def serverconfig = ""
if (env.branch_name == 'develop') {
targetenv = 'qa'
serverconfig = 'qa-server'
} else if (env.branch_name.startswith('release/')) {
targetenv = 'staging'
serverconfig = 'staging-server'
} else if (env.branch_name == 'main') {
targetenv = 'production'
serverconfig = 'prod-server'
timeout(time: 5, unit: 'minutes') {
input message: "确认部署到生产环境?", ok: "部署"
}
}
echo "deploying to ${targetenv} environment..."
sshpublisher(
publishers: [
sshpublisherdesc(
configname: serverconfig,
transfers: [
sshtransfer(
sourcefiles: "${artifact_dir}/${app_name}-${build_version}.jar",
removeprefix: "${artifact_dir}/",
remotedirectory: "/home/deploy/apps"
)
]
)
]
)
sshcommand(
remote: serverconfig,
command: """
cd /home/deploy/apps
version=\$(echo ${app_name}-*.jar | sed 's/${app_name}-\\(.*\\)\\.jar/\\1/')
./scripts/deploy.sh \$version
"""
)
}
}
}这样,不同分支的代码会自动部署到对应环境,且生产环境部署前需要人工确认,避免误操作。
每次构建都会生成详细日志,可通过点击构建编号 → console output 查看。
在部署脚本中,我们已经将日志重定向到文件:
> $log_dir/app.log 2>&1 &
你可以使用 tail -f 实时查看:
tail -f /home/deploy/apps/logs/app.log
我们的 java 应用提供了 /health 和 /info 端点,可用于:
示例 curl 检查:
curl http://localhost:8081/health # 输出:✅ jenkins demo app is running! version: 1.0.0
不要在 jenkinsfile 或配置中硬编码密码。使用 credentials binding:
withcredentials([usernamepassword(credentialsid: 'git-credentials', usernamevariable: 'git_user', passwordvariable: 'git_pass')]) {
sh "git clone https://${git_user}:${git_pass}@your-git-server/repo.git"
}
备份 jenkins 主目录:
sudo tar -czvf jenkins-backup-$(date +%y%m%d).tar.gz /var/lib/jenkins
建议每天自动备份并上传到异地存储。
现象:outofmemoryerror: java heap space
解决:
# 修改 jenkins 启动参数 sudo nano /etc/default/jenkins # 添加或修改: java_opts="-xmx2g -xms512m"
然后重启 jenkins:
sudo systemctl restart jenkins
现象:failed to connect to server
解决:
systemctl status sshdsudo ufw statusssh deploy@server-ip排查步骤:
# 1. 检查进程是否存在 ps aux | grep jenkins-demo-app # 2. 检查端口监听 netstat -tlnp | grep :8081 # 3. 查看应用日志 tail -f /home/deploy/apps/logs/app.log # 4. 检查防火墙 sudo ufw status sudo ufw allow 8081 # 5. 本地测试 curl http://localhost:8081/health
当主节点负载过高时,可以添加构建节点:
pipeline {
agent { label 'java-builder' }
// ... 其他配置
}
在 manage jenkins → manage nodes 中添加新节点。
对于多模块项目,可以并行构建:
stage('parallel build') {
parallel {
stage('module a') {
steps {
dir('module-a') {
sh 'mvn clean package'
}
}
}
stage('module b') {
steps {
dir('module-b') {
sh 'mvn clean package'
}
}
}
}
}避免每次构建都下载 maven 依赖:
stage('build with cache') {
steps {
sh 'mkdir -p ~/.m2'
stash includes: '.m2/**', name: 'maven-cache'
sh 'mvn clean package'
unstash 'maven-cache'
}
}
或者使用 artifact manager 插件进行更高级的缓存管理。
安装 email extension plugin,在 post 部分添加:
post {
success {
emailext (
subject: "success: job '${env.job_name}'",
body: """<p>构建成功!</p>
<p>版本: ${env.build_version}</p>
<p><a href="${env.build_url}" rel="external nofollow" rel="external nofollow" >查看构建详情</a></p>""",
recipientproviders: [[$class: 'developersrecipientprovider']]
)
}
failure {
emailext (
subject: "failed: job '${env.job_name}'",
body: """<p>构建失败!</p>
<p>请尽快修复。</p>
<p><a href="${env.build_url}" rel="external nofollow" rel="external nofollow" >查看构建详情</a></p>""",
recipientproviders: [[$class: 'developersrecipientprovider']]
)
}
}
安装对应插件,在 pipeline 中调用:
// slack 示例
slacksend channel: '#builds', message: "构建${currentbuild.result}: ${env.job_name} #${env.build_number}"
除了单元测试,还可以集成:
示例:集成 sonarqube
stage('code quality') {
steps {
withsonarqubeenv('sonar-server') {
sh 'mvn sonar:sonar'
}
}
}
stage('quality gate') {
steps {
timeout(time: 1, unit: 'hours') {
waitforqualitygate abortpipeline: true
}
}
}通过本文,你已经掌握了:
✅ 在 linux 上安装配置 jenkins
✅ 创建 java spring boot 项目
✅ 编写 jenkins pipeline 实现自动化构建
✅ 通过 ssh 实现自动化部署到生产环境
✅ 设计多环境部署策略
✅ 添加监控、日志、通知机制
✅ 解决常见问题和性能优化
jenkins 作为老牌 ci/cd 工具,虽然界面不如新兴工具现代化,但其稳定性、灵活性和强大的插件生态使其在企业环境中依然占据重要地位。
随着云原生和 kubernetes 的普及,jenkins 也在不断进化,通过 jenkins x、tekton 等项目拥抱新时代。但对于大多数传统企业应用,标准 jenkins 仍然是最佳选择。
当你熟练掌握基础自动化部署后,可以考虑:
自动化部署不是终点,而是 devops 旅程的起点。持续改进、持续交付、持续反馈,才能真正提升软件交付效率和质量。
记住:自动化不是为了取代人,而是让人专注于更有价值的工作。让机器去做重复、易错的任务,让开发者去创造、去创新、去解决问题。
以上就是linux使用jenkins实现自动化部署的完整指南的详细内容,更多关于linux jenkins自动化部署的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论