安装Java 8 ( JRE 或者 JDK 都可以)、清华镜像站
Jenkins和java版本关系
Supported Java versions for the LTS release line are:
2.361.1 (September 2022) and newer
Java 11 or Java 17
2.346.1 (June 2022) and newer
Java 8, Java 11, or Java 17
2.164.1 (March 2019) and newer
Java 8 or Java 11
2.60.1 (June 2017) and newer
Java 8
1.625.1 (October 2015) and newer
Java 7
java -jar jenkins.war #默认端口8080
java -jar jenkins.war --httpPort=8080
java -jar jenkins.war --httpPort=8080 --prefix=/jenkins # 指定URL路径
## 输出截取如下
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
c1f0833ce31d41f4ad2b015867acbe8c
This may also be found at: /root/.jenkins/secrets/initialAdminPassword
1.安装tomcat
安装Tomcat,然后进入tomcat的webapp目录下,直接将jenkins.war放进来
2.设置Jekins环境变量设置
vi /etc/profile
在最后面加上这一句
export JENKINS_HOME=/data/program/tomcat/webapps/Jenkins(jnekins的安装路径)
. /etc/profile #使配置文件生效
3.修改tomcat端口号
#vi /usr/local/apache-tomcat/conf/server.xml
<Connector port="8083" protocol="HTTP/1.1"connectionTimeout="20000" redirectPort="8443" />
保证端口号不冲突
4. 重启tomcat,进入tomcat的安装目录下的bin目录
./startup.sh
tomcat会解压war包,生成一个jenkins文件夹,而且会在root目录下生成一个.jenkins的文件夹
http://localhost:8080
http://localhost:8080/jenkins
可以直接关闭新手入门界面。
在 Manage Jenkins - Manage Plugins - Available 进行插件安装,搜索"local" - 勾选下面两个插件 - 下载安装并重启。
Locale # 安装这个才会有`Locale - Default Language`配置项
Localization: Chinese (Simplified) # 中文,安装完此插件,界面就是中文了
Pipeline # 流水线
matrix-project # Multi-Configuration Projects 中文叫多配置项目
Git # Git仓库
GitLab # GitLab仓库
可在 系统管理 - 系统配置 - Locale - Default Language配置语言 - 填写: zh_CN
对于无法安装的Plugin,如"trilead-api",可在清华大学镜像站手动下载,在Plugin Manager- Advanced页面进行上传安装。
git
yum install -y git
【系统管理】-【管理凭据】-【Jenkins】-【全局凭据】-【添加凭据】-将git账号填在这里
只需要在访问jenkins服务器的网址url地址后加上对应指令即可。
# 1、关闭Jenkins
http://localhost:8080/exit
# 2、重启Jenkies
http://localhost:8080/restart
# 3、重新加载配置信息
http://localhost:8080/reload
新建一个自由风格的job,然后勾选“参数化构建过程 This project is parameterized”,点击“添加参数”,常用的类型有:字符参数、文本参数、选项参数。保存。之后进入该project,点击Build with Parameters即可开始任务。
在声明式Pipeline中的基本语句和表达式遵循Groovy的语法;
流水线顶层必须pipeline{};
agent any可以在任何可用的节点上执行pipeline;
stages包含一系列一个或多个stage 指令, 建议 stages 至少包含一个 stage 指令用于连续交付过程的每个离散部分,比如构建, 测试, 和部署;
steps是每个阶段中要执行的每个步骤。
// Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Build') {
steps {
//
}
}
stage('Test') {
steps {
//
}
}
stage('Deploy') {
steps {
//
}
}
}
}
脚本化流水线, 与声明式一样的是, 是建立在底层流水线的子系统上的。与声明式不同的是, 脚本化流水线实际上是由 Groovy构建的通用 DSL 。 Groovy 语言提供的大部分功能都可以用于脚本化流水线的用户。
脚本化pipeline 顶层是node{};
支持stage;
可以直接使用groovy语言进行编码。
// Jenkinsfile (Scripted Pipeline)
node {
stage('Build') {
//
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
示例
// Jenkinsfile (Scripted Pipeline)
node {
def ENV = 'test'
def REPO = 'xxx'
def IMAGE_PATH = "${ENV}/${REPO}"
stage ('checkout'){
sh """
pwd
ls
docker login --username=100025468706 ccr.ccs.tencentyun.com/clrepo --password=cL@bRep0s1to2y
"""
git branch: 'master', credentialsId: 'xsio', url: 'https://gitlab.cd.xsio.cn/cd_devops/gitlab-runner-helloworld2.git'
commitId = sh returnStdout: true, script: 'git rev-parse HEAD'
commitId = commitId.trim()
// commitId = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
IMAGE = "${env.REGISTRY_SNAPSHOT}/${IMAGE_PATH}:${commitId}"
}
stage('Build') {
//
}
stage('build frontend') {
sh '''
export HOME=/opt/hudson
. ${HOME}/.bashrc
npm i --unsafe-perm
npm run build
'''
}
stage ('build backend'){
sh '''
export HOME=/opt/hudson
. ${HOME}/.bashrc
# mvn -B -DskipTests clean package
chmod +x ./gradlew
./gradlew clean
./gradlew bootRepackage
'''
}
stage('Test') {
echo 'fasttest for test'
}
stage ('package'){
sh """
export HOME=/opt/hudson
docker build -t ${IMAGE} .
docker push ${IMAGE}
docker rmi ${IMAGE} || echo
"""
}
stage ('deploy'){
// 调用创建独立的使用参数化构建的job进行发布
build job: "deploycdk8s/master", parameters: [string(name: 'IMAGE_TAG', value: commitId), string(name: 'SERVICE_NAMES', value: REPO), string(name: 'ENV', value: ENV)]
}
}
那么为什么两种实现pipeline的方式呢?我们可以简单的了解一下其发展的历史。Jenkins是使用Java实现的,所以在很早的时候就引入了groovy作为DSL,管理员可以使用groovy来实现一些自动化和高级的管理功能。因为groovy引擎已经集成到Jenkins,所以在pipeline一开始很自然就使用groovy来编写Jenkinsfile。但是groovy毕竟是一种语言,对于没有太多编程经验的小白学习成本有些高,这个时候声明式的pipeline就出现了,主要是为了降低入门的难度,二者主要区别如下:
声明式pipeline,官方鼓励声明式编程模型,比较适合没有编程经验的初学者。
脚本式pipeline,是基于groovy的DSL语言实现的,为Jenkins用户提供了大量的灵活性性和可扩展性,如果脚本中有大量的逻辑处理则推荐使用。
个人总结二者的主要区别有两点:
2.当我们需要在脚本中写复杂逻辑的时候,通过脚本式pipeline可以方便的编写脚本,例如需要加入循环的逻辑,使用脚本式pipeline
全局变量可以在搭建好的jenkins服务上查看,访问地址:http://jenkins访问地址/pipeline-syntax/globals#env
使用环境变量
Jenkins 流水线通过全局变量 env 提供环境变量,它在 Jenkinsfile 文件的任何地方都可以使用。Jenkins 流水线中可访问的完整的环境变量列表记录在 ``${YOUR_JENKINS_URL}/pipeline-syntax/globals#env``,并且包括:
BUILD_ID
当前构建的 ID,与 Jenkins 版本 1.597+ 中创建的构建号 BUILD_NUMBER 是完全相同的。
BUILD_NUMBER
当前构建号,比如 “153”。
BUILD_TAG
字符串 ``jenkins-${JOB_NAME}-${BUILD_NUMBER}``。可以放到源代码、jar 等文件中便于识别。
BUILD_URL
可以定位此次构建结果的 URL(比如 http://buildserver/jenkins/job/MyJobName/17/ )
EXECUTOR_NUMBER
用于识别执行当前构建的执行者的唯一编号(在同一台机器的所有执行者中)。这个就是你在“构建执行状态”中看到的编号,只不过编号从 0 开始,而不是 1。
JAVA_HOME
如果你的任务配置了使用特定的一个 JDK,那么这个变量就被设置为此 JDK 的 JAVA_HOME。当设置了此变量时,PATH 也将包括 JAVA_HOME 的 bin 子目录。
JENKINS_URL
Jenkins 服务器的完整 URL,比如 https://example.com:port/jenkins/ (注意:只有在“系统设置”中设置了 Jenkins URL 才可用)。
JOB_NAME
本次构建的项目名称,如 “foo” 或 “foo/bar”。
NODE_NAME
运行本次构建的节点名称。对于 master 节点则为 “master”。
WORKSPACE
workspace 的绝对路径。
pipeline {
agent any
parameters {
// 填写字符串
string(name: "cdp_version", defaultValue: "", description: "")
//下拉选择,默认将 choices 列表中的第一个值作为默认值。
choice(name: 'cdp_profiles', choices: ['small', 'medium', 'large'], description: 'Esxi Server profiles.')
}
environment {
CDP_VERSION = "$params.cdp_version"
CDP_PROFILES = "$params.cdp_profiles"
}
stages {
stage("Test Job") {
steps{
script {
sh """
// 引用变量
echo "Deploying ${params.cdp_version} version"
export cdp_profiles=${CDP_PROFILES}
"""
}
}
}
// 调用其他 Job,无返回值
stage('Trigger Another Job') {
steps {
build job: 'boot-auto-test-rlx',
parameters: [string(name: 'cdp_version', value: "${env.CDP_VERSION}"),
string(name: 'cdp_profiles', value: "${env.CDP_PROFILES}")],
wait: false
}
}
// 调用其他 Job,带返回值
stage('Trigger Another Job And Return') {
steps {
script {
def buildResult = build job: 'boot-auto-test-rlx',
parameters: [string(name: 'cdp_version', value: "${env.CDP_VERSION}"),
string(name: 'cdp_profiles', value: "${env.CDP_PROFILES}")],
wait: false
// 输出跳转链接到指定的构建ID
echo "Triggered build URL: ${buildResult.getAbsoluteUrl()}"
}
}
}
}
}
个人尝试了下,该方式是通过命令行直接调curl去发POST请求的方式来触发job的构建。对于用openid管理的Jenkins,需要带上参数--user USER:PASSWORD,其中的USER和PASSWORD不是你的openID登录的账号密码,而是登录后显示在Jenkins中的User Id和API Token,它们的的查看方式如下:
用openID登录jenkins —> 点击右上角的用户名,进入用户个人页面 —> 点击左边的设置,打开设置页面 —> API Token,Show Api Token...
如果需要参数化构建job,则要加上--data-urlencode json='{"parameter": [{"name":"param_name1","value":"param_value1"}, {"name":"param_name2","value":"param_value2"}]}'
显然,这种方式比较繁琐,很容易出现因格式不正确导致触发任务失败,而且这种方式不能帮助我们获取更多的关于job的信息以便于我们后续对job的状态进行跟踪。
#定义远程的jenkins master server的url,以及port
JENKINS_URL='http://jenkins.xx.xxx.cn/'
#定义用户的User Id 和 API Token,获取方式同上文
USER='xxx'
TOKEN='xxxx'
#获取job名为job_name的job的相关信息
JOB_NAME='build_wechat-plugin'
#获取job名为job_name的job的lastBuild的buildNumber
build_number=$(curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/buildNumber)
echo "lastBuildNumber: ${build_number}"
#获取job名为job_name的job的某次构建的执行结果状态
#判断job名为job_name的job的某次构建是否还在构建中
#获取job名为job_name的job的某次构建的Console Output
job_console_output=$(curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/consoleFull)
job_console_output=$(curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/${build_number}/consoleFull)
#echo "${job_console_output}"
echo "${job_console_output}" |grep "docker push"
# 获取构建控制台输出,用这个,比consoleFull少了没用的HTML信息。
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/logText/progressiveText
#获取最近一次成功的build的时间
job_timestamp=$(curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/buildTimestamp)
#echo ${job_timestamp}
#结果为: 4/1/22 4:30 PM 转换: date -d "4/1/22 4:30 PM" +"%Y-%m-%d %H:%M:%S"
job_timestamp=$(date -d "${job_timestamp}" +"%Y-%m-%d %H:%M:%S")
echo ${job_timestamp}
#结果为: 2022-04-01 16:30.00
#获取最近一次成功的build的描述,不确定是否有用
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/description
#获取最近一次成功的build的num
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastSuccessfulBuild/buildNumber
#获取最近一次稳定的build的num
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastStableBuild/buildNumber
#获取最近一次失败的build的num
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastFailedBuild/buildNumber
#查询job名为job_name的job的lastBuild的状态 json 格式
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/api/json
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/api/json | sed 's/,/\n/g'
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/api/json | sed 's/,/\n/g' | sed -n 's/"result":"\([^"]*\)"/\1/p'
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/api/json | sed 's/,/\n/g' | sed -n 's/"timestamp":\([^,]*\)/\1/p' | awk 'NR==1 {print $0}'
#curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/lastBuild/api/xml
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/${build_number}/api/json
#curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/${build_number}/api/xml
curl -s --user ${USER}:${TOKEN} ${JENKINS_URL}/job/${JOB_NAME}/buildHistory/ajax
Python-Jenkins官网
Python-Jenkins Doc
#pip install python-jenkins
import jenkins
import re
#定义远程的jenkins master server的url,以及port
jenkins_server_url='http://jenkins.xx.xxx.cn/'
#定义用户的User Id 和 API Token,获取方式同上文
user_id='xxx'
api_token='xxxx'
#实例化jenkins对象,连接远程的jenkins master server
server=jenkins.Jenkins(jenkins_server_url, username=user_id, password=api_token)
#构建job名为job_name的job(不带构建参数)
#server.build_job(job_name)
#String参数化构建job名为job_name的job, 参数param_dict为字典形式,如:param_dict= {"param1":“value1”, “param2”:“value2”}
#server.build_job(job_name, parameters=param_dict)
#获取job名为job_name的job的相关信息
job_name = 'build_wechatplugin'
job_result = server.get_job_info(job_name)
print(job_result)
#获取job名为job_name的job的最后次构建号
build_number = server.get_job_info(job_name)['lastBuild']['number']
print(build_number)
#获取job名为job_name的job的某次构建的执行结果状态
job_status = server.get_build_info(job_name,build_number)['result']
print(job_status)
#判断job名为job_name的job的某次构建是否还在构建中
is_building = server.get_build_info(job_name,build_number)['building']
print(is_building)
#获取job名为job_name的job的某次构建的Console Output
job_console_output = server.get_build_console_output(job_name,build_number)
#print(job_console_output)
pattern = re.compile('docker push .*?\n',re.S)
result = re.search(pattern, job_console_output)
print(result.group(0).strip())