Hi I’m Shendi
Jenkins入门使用详解,实现构建部署运行
Jenkins简介
Jenkins 是一个用 Java 编写的开源自动化工具
Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。
CI 指持续集成,属于开发人员的自动化流程
CD 指持续交付和/或持续部署,这些相关概念有时会交叉使用。两者都事关管道后续阶段的自动化,但它们有时也会单独使用,用于说明自动化程度。
Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。
下载安装运行
对于设备的要求:https://www.jenkins.io/zh/doc/book/installing/#prerequisites
进入 jenkins 官网下载:https://www.jenkins.io/zh/download/
我系统是windows,所以选的windows,下载完后是一个msi的文件,打开运行进行安装
一路next,到如下窗口
第一个选项是将服务运行在本地系统上,第二个是运行在指定用户上,可以直接选择第一个选项然后Next
然后是运行的端口,默认是8080,点Test Port然后继续Next
选择JDK所在地址,Next,Next,Install,开始安装。
在windows上可能会因为没有权限而按照失败,报2503等错误
解决办法如下
- 打开管理员权限的命令行,例如Win+X,然后按下A
- 输入
msiexec /package jenkins.msi的文件路径
后面的步骤和上面一致
安装完成后,目录结构如下
进行以下操作
- 打开终端进入到下载目录.
- 运行命令
java -jar jenkins.war --httpPort=8080
. - 打开浏览器进入链接
http://localhost:8080
.
我使用的是windows,msi方式安装,所以第二步就不需要了,因为安装完后会自动启动(安装时填写的端口)
进入链接,界面如下,要等待
大概几秒钟,如果一直都是这个界面,那就打开浏览器控制台(F12),查看是否有以下的错误
GET http://localhost:8080/login?from=%2F 503 (Service Unavailable)
如果有,则需要进行以下操作
- 进入jenkins的工作目录:
C:\ProgramData\Jenkins
- 进入.jenkins目录,打开hudson.model.UpdateCenter.xml进行修改
- 将url中的
https://updates.jenkins.io/update-center.json
修改为http://mirror.xmission.com/jenkins/updates/update-center.json
进入jenkins安装目录,使用以下命令重启
jenkins restart
访问链接,界面显示如下
按照说明,进行配置即可,后面创建密码,如果选择的使用admin,那么密码默认就是上面解锁 Jenkins 的密码
dashboard界面如下
创建您的第一个Pipeline,实现hello,world
New Item介绍
- Freestyle project(自由风格项目):这个选项允许用户创建一个自定义的项目,可以执行任何任务,无论是构建、测试、部署还是其他工作。
- Pipeline(流水线项目):这个选项允许用户创建一个Jenkins Pipeline,在Pipeline中定义了一系列流程和任务,可以自动化构建、测试、打包、发布和部署过程。
- Multibranch Pipeline(多分支流水线项目):这个选项可以创建一个多分支Pipeline项目,同时支持不同的分支构建和测试。
- Folder:文件夹,用于组织和管理 Jenkins 中的多个项目
新建Item,输入工程的名称(例如 My Pipeline) ,选择多分支流水线(Multibranch Pipeline),确定
会进入到新建Item的Configuration(配置),点击增加源(Add Source),选择您想要使用的仓库类型并填写详细信息.
填写对应信息,例如我选择的Git,桌面上有一个Test文件夹,使用 git init
初始化,如何将路径填到项目仓库
点击保存,就会开始运行扫描,最终看到Success的信息就代表成功了
在配置好 Pipeline 之后,Jenkins 会自动检测您仓库中创建的任何新的分支或合并请求, 并开始为它们运行 Pipelines。
在项目下新建一个文件夹,命名为 Jenkinsfile
,注意大小写 ,具体查看Jenkins工程的配置内容
Jenkinsfile文件具体内容可以参考官方文档
例如
pipeline {
agent any
stages {
stage('Hello') {
steps {
sh 'echo hello,world'
}
}
}
}
更改了内容重新 git add
,git commit
然后在 Jenkins 中点立刻Scan…
然后查看Scan多分支流水线日志,有这样的内容代表 Jenkinsfile 被找到了
Checking branches...
Checking branch master
‘Jenkinsfile’ found
Met criteria
接下来可以点击状态来查看,会发现有内容了,但是运行是失败
点击右边的 #8
,然后选择 Console Output
查看日志
可以看到报错内容如下
ERROR: Checkout of Git remote 'C:\Users\Administrator\Desktop\Test' aborted because it references a local directory, which may be insecure. You can allow local checkouts anyway by setting the system property 'hudson.plugins.git.GitSCM.ALLOW_LOCAL_CHECKOUT' to true.
这个是因为我使用的本地的git用来测试,所以需要配置一下,在jenkins安装目录找到 jenkins.xml
打开,并修改,加上这一句
-Dhudson.plugins.git.GitSCM.ALLOW_LOCAL_CHECKOUT=true
然后使用 jenkins restart
来重启jenkins
进入Jenkins,重新运行,发现报错改为了找不到文件
java.io.IOException: CreateProcess error=2, 系统找不到指定的文件。
at java.base/java.lang.ProcessImpl.create(Native Method)
at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:494)
at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:159)
Caused: java.io.IOException: Cannot run program "nohup" (in directory "C:\ProgramData\Jenkins\.jenkins\workspace\Test_master"): CreateProcess error=2, 系统找不到指定的文件。
因为我使用的是windows,所以要更改Jenkinsfile文件,将其中的sh改为bat(sh是在linux中使用的)
改完后重新 git add
,git commit
,jenkins中重新扫描运行
可以看到运行成功了
点进去查看Console Output,可以看到输出的 hello,world
配置
在Jenkins主页点击Manager Jenkins,Global Tool Configuration来配置Maven,JDK,Git等。
Jenkinsfile
执行多个步骤
Pipelines 由多个步骤(step)组成,允许你构建、测试和部署应用。 Jenkins Pipeline 允许您使用一种简单的方式组合多个步骤, 以帮助您实现多种类型的自动化构建过程。
可以把“步骤(step)”看作一个执行单一动作的单一的命令。 当一个步骤运行成功时继续运行下一个步骤。 当任何一个步骤执行失败时,Pipeline 的执行结果也为失败。
当所有的步骤都执行完成并且为成功时,Pipeline 的执行结果为成功。
具体可以直接参考官方文档:https://www.jenkins.io/zh/doc/pipeline/tour/running-multiple-steps/
timeout
代表超时,retry
代表重试/循环,可嵌套使用,例如执行五次 ./flakey-deploy.sh
,如果超过三分钟则超时,状态为失败
steps {
timeout(time: 3, unit: 'MINUTES') {
retry(5) {
sh './flakey-deploy.sh'
}
}
}
当 Pipeline 运行完成时,你可能需要做一些清理工作或者基于 Pipeline 的运行结果执行不同的操作, 这些操作可以放在 post
部分。
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'echo "Fail!"; exit 1'
}
}
}
post {
always {
echo 'This will always run'
}
success {
echo 'This will run only if successful'
}
failure {
echo 'This will run only if failed'
}
unstable {
echo 'This will run only if the run was marked as unstable'
}
changed {
echo 'This will run only if the state of the Pipeline has changed'
echo 'For example, if the Pipeline was previously failing but is now successful'
}
}
}
定义执行环境
您可能已经注意到每个示例中的 agent
指令。 agent
指令告诉Jenkins在哪里以及如何执行Pipeline或者Pipeline子集。 正如您所预料的,所有的Pipeline都需要 agent
指令。
在执行引擎中,agent
指令会引起以下操作的执行:
- 所有在块block中的步骤steps会被Jenkins保存在一个执行队列中。 一旦一个执行器 executor 是可以利用的,这些步骤将会开始执行。
- 一个工作空间 workspace 将会被分配, 工作空间中会包含来自远程仓库的文件和一些用于Pipeline的工作文件
例如
pipeline {
agent {
docker { image 'node:7-alpine' }
}
stages {
stage('Test') {
steps {
sh 'node --version'
}
}
}
}
agent
指令更多选项和相关信息,可以查看 语法参考 。
使用环境变量
环境变量可以像下面的示例设置为全局的,也可以是阶段(stage)级别的。 如你所想,阶段(stage)级别的环境变量只能在定义变量的阶段(stage)使用。
使用 environment
来设置环境变量,例如
pipeline {
agent any
environment {
DISABLE_AUTH = 'true'
DB_ENGINE = 'sqlite'
}
stages {
stage('Build') {
steps {
sh 'printenv'
}
}
}
}
上面的 printenv
是Linux用于显示系统环境变量与值的命令
在使用中,可以通过 ${}
的方式来获取,也可以使用 ${env.}
来获取,建议使用 env
这种方式,例如
pipeline {
agent any
environment {
DISABLE_AUTH = 'true'
DB_ENGINE = 'sqlite'
}
stages {
stage('Build') {
steps {
bat 'echo ${env.DISABLE_AUTH}'
}
}
}
}
记录测试和构建结果
虽然测试是良好的持续交付过程中的关键部分,但大多数人并不希望筛选数千行控制台输出来查找有关失败测试的信息。 为了简化操作,只要您的测试运行时可以输出测试结果文件,Jenkins 就可以记录和汇总这些测试结果。 Jenkins 通常与 junit
步骤捆绑在一起,但如果您的测试运行结果无法输出 JUnit 样式的 XML 报告, 那么还有其他插件可以处理任何广泛使用的测试报告格式。
Jenkins的记录测试和构建结果通常用于测试环境中
例如
pipeline {
agent any
stages {
stage('Build') {
steps {
sh './gradlew build'
}
}
stage('Test') {
steps {
sh './gradlew check'
}
}
}
post {
always {
archiveArtifacts artifacts: 'build/libs/**/*.jar', fingerprint: true
junit 'build/reports/**/*.xml'
}
}
}
其中 stage(‘Test’) 部分是执行测试用例,执行的Gradle的命令,maven则 mvn test
通过 archiveArtifacts
步骤和文件匹配表达式可以很容易的完成构建结果记录和存储
清理和通知
因为 post
部分保证在 Pipeline 结束的时候运行, 所以我们可以添加通知或者其他的步骤去完成清理、通知或者其他的 Pipeline 结束任务。
参考官方文档:https://www.jenkins.io/zh/doc/pipeline/tour/post/
部署
大多数最基本的持续交付 Pipeline 至少会有三个阶段:构建、测试和部署,这些阶段被定义在 Jenkinsfile
中。 这一小节我们将主要关注部署阶段,但应该指出稳定的构建和测试阶段是任何部署活动的重要前提。
stage代表阶段
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building'
}
}
stage('Test') {
steps {
echo 'Testing'
}
}
stage('Deploy') {
steps {
echo 'Deploying'
}
}
}
}
阶段即为部署环境
一个常见的模式是扩展阶段的数量以获取额外的部署环境信息, 如 “staging” 或者 “production”,如下例所示。
stage('Deploy - Staging') {
steps {
sh './deploy staging'
sh './run-smoke-tests'
}
}
stage('Deploy - Production') {
steps {
sh './deploy production'
}
}
在这个示例中,我们假定 ./run-smoke-tests
脚本所运行的冒烟测试足以保证或者验证可以发布到生产环境。 这种可以自动部署代码一直到生产环境的 Pipeline 可以认为是“持续部署”的一种实现。 虽然这是一个伟大的想法,但是有很多理由表明“持续部署”不是一种很好的实践, 即便如此,这种方式仍然可以享有“持续交付”带来的好处。 [1] Jenkins Pipeline可以很容易支持两者。
人工确认
通常在阶段之间,特别是不同环境阶段之间,您可能需要人工确认是否可以继续运行。 例如,判断应用程序是否在一个足够好的状态可以进入到生产环境阶段。 这可以使用 input
步骤完成。 在下面的例子中,“Sanity check” 阶段会等待人工确认,并且在没有人工确认的情况下不会继续执行。
pipeline {
agent any
stages {
/* "Build" and "Test" stages omitted */
stage('Deploy - Staging') {
steps {
sh './deploy staging'
sh './run-smoke-tests'
}
}
stage('Sanity check') {
steps {
input "Does the staging environment look ok?"
}
}
stage('Deploy - Production') {
steps {
sh './deploy production'
}
}
}
}
实现自动化部署
一般会使用一台单独的服务器安装 Jenkins,然后通过远程命令的方式来操作其他服务器
需要在Jenkins中安装插件:Publish Over SSHVersion
因我目前只有一台服务器,所以不使用远程部署方式
这里使用一个SpringBoot项目(Maven)作为示例,其余语言/项目大同小异
可以把 Jenkins 理解为从 Git 上拉取代码,然后执行命令的工具
拉取的代码在哪个文件夹?
windows一般在 C:\ProgramData\Jenkins\.jenkins\workspace
中
可以在Jenkins的运行控制台中查看到路径
Jenkinsfile
分为构建,测试,运行三阶段
Maven中,构建使用 mvn clean package
,但是默认会在构建后执行测试,只需要构建则加上-DskipTests
测试使用 mvn test
命令
运行一般会格外写一个脚本,Linux上写sh,Windows上写bat,Java项目的话,内容为
java -Dfile.encoding=UTF-8 -jar target/my.jar
Jenkinsfile文件内容如下
pipeline {
agent any
stages {
stage('Build') {
steps {
bat 'mvn -DskipTests clean package'
}
}
stage('Test') {
steps {
bat 'mvn test'
}
}
stage('Deliver') {
steps {
bat 'run'
}
}
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
需要注意的是Deliver部分,去运行了一个名为 run.bat
的脚本文件,需要确保这个文件不会被卡住,例如上面描述的 java -jar,运行后就会一直在执行Java程序了,导致阶段一直不能被完成。
在windows中可以通过加上 start
来在新命令行运行
start java -Dfile.encoding=UTF-8 -jar target/my.jar
在windows中,通常控制台会报错:拒绝访问。
具体解决办法我写了另一篇文章:Jenkins在Windows上运行start java报拒绝访问及阶段执行完后取消自动关闭程序的问题解决 - https://sdpro.top/blog/html/article/1050.html
这样又会出现一个问题,因为是自动化,程序运行后不会被关闭,会导致代码更新后再次运行报错,端口被占用的问题
为了解决这个问题,需要在最开始的时候运行关闭程序的脚本,可自行编写或百度到关闭程序的脚本,例如通过端口来关闭
set port=9915
set portpid=none
FOR /F "tokens=1-5" %%i IN ('netstat -ano^|findstr ":%port%"') DO @set portpid=%%m
if not %portpid% ==none ( taskkill /pid %portpid% /f ) else ( echo here is no pid for port %port% )
echo port:%port%
最终的Jenkinsfile内容如下
pipeline {
agent any
stages {
stage('Init') {
steps {
bat 'stop'
}
}
stage('Build') {
steps {
bat 'mvn -DskipTests clean package'
}
}
stage('Test') {
steps {
bat 'mvn test'
}
}
stage('Deliver') {
steps {
withEnv(['JENKINS_NODE_COOKIE=noKill']) {
bat 'run'
}
}
}
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
最后,当代码有修改时只需要上到git,然后在Jenkins重新构建即可
当然,也可以配置触发器等…
END