1.安装Jenkins
Jenkins安装手册
https://www.jenkins.io/doc/book/installing/
Jenkins官方的下载地址:
https://www.jenkins.io/download/
找到合适的版本,使用wget命令进行下载
wget https://get.jenkins.io/war-stable/2.452.3/jenkins.war
启动jenkis
java -jar jenkins.war
可能出现端口被占用的情况(因为Jenkins默认端口是8080,很容易冲突)
java.net.BindException: Address already in use
at java.base/sun.nio.ch.Net.bind0(Native Method)
at java.base/sun.nio.ch.Net.bind(Net.java:565)
at java.base/sun.nio.ch.ServerSocketChannelImpl.netBind(ServerSocketChannelImpl.java:344)
at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:301)
at org.eclipse.jetty.server.ServerConnector.openAcceptChannel(ServerConnector.java:339)
Caused: java.io.IOException: Failed to bind to 0.0.0.0/0.0.0.0:8080
at org.eclipse.jetty.server.ServerConnector.openAcceptChannel(ServerConnector.java:344)
at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:304)
at org.eclipse.jetty.server.Server.lambda$doStart$0(Server.java:402)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:1024)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at org.eclipse.jetty.server.Server.doStart(Server.java:398)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
at winstone.Launcher.<init>(Launcher.java:205)
Caused: java.io.IOException: Failed to start Jetty
at winstone.Launcher.<init>(Launcher.java:209)
at winstone.Launcher.main(Launcher.java:496)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at executable.Main.main(Main.java:351)
可以加上端口号配置(Jenkins安装手册有讲到)
java -jar jenkins.war --httpPort=9090
# 直接后台运行
nohup java -jar jenkins.war --httpPort=9090 & > info.log
指定端口号之后启动日志如下:
Running from: /home/ubuntu/jenkins/jenkins.war
webroot: /home/ubuntu/.jenkins/war
2024-07-19 09:45:55.111+0000 [id=1] INFO winstone.Logger#logInternal: Beginning extraction from war file
2024-07-19 09:45:55.228+0000 [id=1] WARNING o.e.j.s.handler.ContextHandler#setContextPath: Empty contextPath
2024-07-19 09:45:55.294+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: jetty-10.0.20; built: 2024-01-29T20:46:45.278Z; git: 3a745c71c23682146f262b99f4ddc4c1bc41630c; jvm 21.0.3+9-Ubuntu-1ubuntu122.04.1
2024-07-19 09:45:55.797+0000 [id=1] INFO o.e.j.w.StandardDescriptorProcessor#visitServlet: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
2024-07-19 09:45:55.857+0000 [id=1] INFO o.e.j.s.s.DefaultSessionIdManager#doStart: Session workerName=node0
2024-07-19 09:45:56.604+0000 [id=1] INFO hudson.WebAppMain#contextInitialized: Jenkins home directory: /home/ubuntu/.jenkins found at: $user.home/.jenkins
2024-07-19 09:45:56.985+0000 [id=1] INFO o.e.j.s.handler.ContextHandler#doStart: Started w.@13006998{Jenkins v2.452.3,/,file:///home/ubuntu/.jenkins/war/,AVAILABLE}{/home/ubuntu/.jenkins/war}
2024-07-19 09:45:56.999+0000 [id=1] INFO o.e.j.server.AbstractConnector#doStart: Started ServerConnector@45afc369{HTTP/1.1, (http/1.1)}{0.0.0.0:9090}
2024-07-19 09:45:57.031+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: Started Server@f0f2775{STARTING}[10.0.20,sto=0] @2674ms
2024-07-19 09:45:57.032+0000 [id=32] INFO winstone.Logger#logInternal: Winstone Servlet Engine running: controlPort=disabled
2024-07-19 09:45:57.305+0000 [id=40] INFO jenkins.InitReactorRunner$1#onAttained: Started initialization
2024-07-19 09:45:57.314+0000 [id=39] INFO jenkins.InitReactorRunner$1#onAttained: Listed all plugins
2024-07-19 09:45:58.456+0000 [id=40] INFO jenkins.InitReactorRunner$1#onAttained: Prepared all plugins
2024-07-19 09:45:58.461+0000 [id=39] INFO jenkins.InitReactorRunner$1#onAttained: Started all plugins
2024-07-19 09:45:58.474+0000 [id=39] INFO jenkins.InitReactorRunner$1#onAttained: Augmented all extensions
2024-07-19 09:45:58.728+0000 [id=38] INFO jenkins.InitReactorRunner$1#onAttained: System config loaded
2024-07-19 09:45:58.729+0000 [id=38] INFO jenkins.InitReactorRunner$1#onAttained: System config adapted
2024-07-19 09:45:58.729+0000 [id=38] INFO jenkins.InitReactorRunner$1#onAttained: Loaded all jobs
2024-07-19 09:45:58.731+0000 [id=38] INFO jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated
2024-07-19 09:45:58.811+0000 [id=54] INFO hudson.util.Retrier#start: Attempt #1 to do the action check updates server
2024-07-19 09:45:59.394+0000 [id=38] INFO jenkins.install.SetupWizard#init:
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
.................
This may also be found at: /home/ubuntu/.jenkins/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************
使用HTTP访问9090端口可以进入Jenkins页面,进入页面可以查看~/.jenkins/secrets/initialAdminPassword
当中的密码,进行手动登录。
http://localhost:9090
身份验证完成之后,进入到插件安装的环节,选择需要的插件进行安装。
2.Jenkis构建项目的插件安装&配置
2.1 Publish Over SSH安装和配置
这个插件的作用是支持使用SSH的方式将文件推送到目标机器上完成部署,比如我在当前机器上编译出来一个Jar包,希望推送到目标服务器上并使用java -jar
完成服务的部署。
安装完成插件之后,需要配置远程服务器信息,配置路径如下:“Dashboard”-“系统管理”-“System”,搜索并找到Publish Over SSH
对应的配置。
首先配置密码:需要从Passphrase
,Key
,和Path To key
三个选择一个进行配置。
- 如果是简单的密码登录的方式(用户名+密码的方式),在passphrase当中配置具体的密码就行。
- 如果是基于RSA密钥的方式,则需要将公钥上传到服务器、私钥填入Jenkins。
- 公钥需要从本地拷贝放到放到远程目标服务器的
~/.ssh/authorized_keys
文件当中,格式参考ssh-rsa ...... {username}@{email}@qq.com
。 - 在
Path to key
处填入私钥的文件路径,也可以在Key
处填入私钥的内容,格式参考:-----BEGIN OPENSSH PRIVATE KEY----- ..... -----END OPENSSH PRIVATE KEY-----
。
- 公钥需要从本地拷贝放到放到远程目标服务器的
接着在下面的SSH Server当中配置远程的机器的hostname,username,以及部署时对于文件需要推送到目标服务器的基础路径。
在填写完成SSH相关的信息之后,可以点击右下角的Test Configuration
去测试配置是否成功,能否连接上配置的目标服务器。
2.2 Jenkins环境JDK安装
运行Java应用必须是用到JDK,因此需要配置JDK才能正常执行。JDK的配置路径如下:“Dashboard"-“系统管理”-"全局工具配置”。
在这里安装JDK有以下几种方式:
- 可以手动指定一下JAVA_HOME的路径(如果本地已经有安装JDK);
- 可以从
java.sun.com
下载/压缩包的方式自动安装JDK(本机没安装JDK的情况)。
2.3 Jenkins环境Gradle/Maven安装
Maven和Gradle的安装类似,配置路径:“Dashboard”-“系统管理”-“全局工具配置”,在这里选择需要安装的Maven版本/Gradle版本即可。
3.在Jenkins当中基于自动化部署项目
3.1基于Gradle构建一个Java项目并部署到远程服务器
正常的部署一个Gradle工程的步骤如下:
- 1.从Git仓库拉取代码。
- 2.使用Gradle构建并输出jar包。
- 3.使用
java -jar
运行生成的jar包。
在Jenkins当中,构建一个Gradle工程的步骤也完全一致,只是使用了Jenkins配置的方式实现。
(1) Jenkins新任务创建
在Jenkins首页选择"新建任务"
进入到下面的项目创建页面,给项目起个名,选择"构建一个自由风格的软件项目"这个项目类型,也可以根据需要选择别的项目类型。
(2) 配置Git仓库地址用于代码拉取
接着是配置Git地址,配置的是需要从哪个地方去拉去代码完成构建。
- Respository URL:填写远程Git仓库的地址。
- Credential:填写登录远程Git仓库的账号密码。
- Branches to build:填写要去进行构建的代码分支。
(3) 利用构建工具(Maven/Gradle)完成项目的构建并输出产物
在拉取到项目之后,需要利用构建工具(Maven/Gradle)完成项目的构建,并输出最终的产物(构件,Archive)。
在Build Steps
处选择"增加构建步骤",我们这里使用Gradle进行项目的构建,因此这里选择"Invoke Gradle script"。
在选择Invoke Gradle script
之后,进入到下面的页面,我们选择Gradle执行的任务,比如我们平时执行构建使用的命令是./gradlew build
,那么我们在这里就填入任务名称build
。
上面的构建步骤,对于Java应用来说,最终会输出一个Jar包,接下来,我们需要配置,将这个Jar包上传到哪里?这个Jar包如何进行部署到目标服务器?
(4) 配置部署目标服务器并配置服务启动命令
在"构建后操作"当中,选择Send build artifacts over SSH
,执行下面步骤。
- 在Name处配置好我们之前安装
Publish over SSH
时配置的目标服务器的机器名称。 - SourceFiles:配置我们需要上传到目标文件的文件的内容,如下的配置代表需要将工程目录下的
build/libs/*.jar
全部上传到目标服务器。 - 在Remote directory当中选择上传到目标服务器的地址,会以
Publish over SSH
配置的地址作为基地址,我们这里配置的是相当于地址nativeproject
,最终的上传路径会是/home/ubuntu/project/nativeproject
。 - Exec command:在将Jar包上传到目标服务器之后,需要指定的应用启动命令,我们这里使用
java -jar
的方式去启动SpringBoot项目。
3.2 基于Jenkins Pipeline构建项目
在创建Jenkins任务时,选择流水线任务,可以通过指定Jenkinsfile的方式去构建项目。
Jenkinsfile基于Groovy语法进行脚本的编写,可以实现更加灵活的项目构建逻辑。
参考如下:
pipeline {
agent any
// 配置环境变量, 后面可以根据env.xxx去获取到环境变量信息
environment {
SERVER_NAME = 'tencentyun'
REMOTE_DIR = 'nativeproject2'
JAR_NAME = "build/libs/*.jar"
GIT_URL = 'git@github.com:wanna280/nativeproject.git'
GIT_BRANCH = 'main'
}
stages {
// Git拉取代码
stage("Checkout") {
steps {
git branch: '${GIT_BRANCH}', url: '${GIT_URL}'
}
}
// 使用Shell去执行Gradle编译Jar包, 会放到build/libs/目录下
stage('Build') {
steps {
sh './gradlew clean build'
}
}
// 上传文件并启动服务器
stage('Upload And Start Server') {
steps {
sshPublisher(publishers: [
sshPublisherDesc(
configName: "${env.SERVER_NAME}", // 部署的目标服务器的名字, 需要和Publish Over SSH配置的名称对应
transfers: [
sshTransfer(
sourceFiles: 'build/libs/*.jar', // 需要传输到远程的文件
remoteDirectory: "${env.REMOTE_DIR}", // 上传到远程服务器路径, 会以Publish Over SSH配置的路径作为基础路径, 这里填相对路径
removePrefix: '', // 上传到服务器之后, 需要把文件去除的前缀, 比如文件是build/libs/xx.jar, 配置"build/libs/",那么上传到服务器之后路径就会去掉前缀
execCommand: """
pwd
cd project/nativeproject2/
pwd
nohup java -jar ${env.JAR_NAME} --server.port=9190 > info.log 2>&1 &
""" // 上传到远程服务器之后, 需要执行的命令, 需要注意的是: 当前路径是Home目录
)
],
verbose: true
)
])
}
}
}
post {
success {
echo 'Deployment succeeded!'
}
failure {
echo 'Deployment failed!'
}
}
}
我们定义三个阶段(Stage
):
Checkout
用于通过Git拉取代码。Build
用于执行Shell脚本,从而执行Gradle命令完成Gradle项目的构建。Upload And Start Server
,在Gradle构建完成项目之后会输出Jar包到build/libs/
目录下,在这个阶段当中我们通过SSH的方式将生成的Jar包上传到目标服务器当中,并通过execCommand
去配置部署目标服务器要执行的Shell脚本。