当前位置: 首页 > news >正文

Jenkins详解(三)

Jenkins详解(三)

目录
  • Jenkins详解(三)
    • 1、Jenkins介绍
    • 2、Jenkins CI/CD 流程
    • 3、部署环境
      • 3.1 环境准备
      • 3.2 安装GitLab
      • 3.3 初始化GitLab
      • 3.4 GitLab中文社区版补丁包安装
      • 3.5 修改GitLab配置文件/etc/gitlab/gitlab.rb
      • 3.6 在宿主机输入 http://192.168.200.26:88 地址就可以访问了
      • 3.7 创建一个项目
      • 3.8 配置GitLab的SSH密钥连接方式
      • 3.9 尝试将本地仓库代码推送到私有GitLab
    • 4、Jenkins 安装配置
      • 4.1 安装 java 环境
      • 4.2 安装和配置maven环境
      • 4.3 安装 jenkins
      • 4.4 配置文件
        • 4.4.1 查询 yum 下载 Jenkins 安装的文件
        • 4.4.2 修改配置文件
        • 4.4.3 启动 jenkins
        • 4.4.4 验证安装
      • 4.5 jenkins配置(web页面)
        • 4.5.1 登录 jenkins web界面
        • 4.5.2 管理员密码获取
        • 4.5.3 初始化安装插件
        • 4.5.4 创建第一个管理员用户
        • 4.5.5 url 配置
        • 4.5.6 安装完成
        • 4.5.7 配置 jdk、git、maven
    • 5、使用Jenkins
      • 5.1 修改默认源,改成国内源
      • 5.2 Jenkins 用户权限管理
        • 5.2.1 用户管理背景
        • 5.2.2 安装用户管理插件
        • 5.2.3 开启该插件功能
        • 5.2.4 验证用户管理
          • 5.2.4.1 匿名用户不可读写(全局安全配置)
          • 5.2.4.2 开启允许用户注册(全局安全配置)
          • 5.2.4.3 注册一个新用户
          • 5.2.4.4 重新登录新创建的 xiaozhao 用户,但是显示没有任何权限
        • 5.2.5 权限划分
          • 5.2.5.1 添加用户
          • 5.2.5.2 添加项目
          • 5.2.5.3 给予 xiaozhao 用户分配 user 角色
          • 5.2.5.4 针对指定用户分配项目角色
          • 5.2.5.5 创建两个项目分别以A-和B-开头的项目
          • 5.2.5.6 新建视图
          • 5.2.5.7 检测项目
      • 5.3 Jenkins 参数化构建
        • 5.3.1 Extended 插件
          • 5.3.1.1 安装插件
          • 5.3.1.2 项目配置
          • 5.3.1.3 选择安装过的插件
          • 5.3.1.4 进行配置
          • 5.3.1.5 构建选择执行shell进行测试
          • 5.3.1.6 参数化配置已经生效
          • 5.3.1.7 构建 test02
          • 5.3.1.8 数据来源选择文件
        • 5.3.2 Git 插件
          • 5.3.2.1 安装插件 Git Parameter
          • 5.3.2.2 进行相关配置
          • 5.3.2.3 配置 git 仓库
          • 5.3.2.4 进行构建
      • 5.4 Jenkins Master-Slave 架构
        • 5.4.1 安装
        • 5.4.2 配置
        • 5.4.3 构建
        • 5.4.4 扩展
      • 5.5 Jenkins pipeline
        • 5.5.1 概览
        • 5.5.2 实操
          • 5.5.2.1 新建任务
          • 5.5.2.2 添加项目Git参数化构建
          • 5.5.2.3 编写 pipeline 脚本
          • 5.5.2.4 构建测试
      • 5.6 Jenkins 构建邮件状态通知
        • 5.6.1 前提
        • 5.6.2 基础配置
        • 5.6.3 配置到项目中
      • 5.7 Jenkins 流水线自动化发布PHP项目
        • 5.7.1 前提
        • 5.7.2 配置
          • 5.7.2.1 创建job
          • 5.7.2.2 参数化构建
          • 5.7.2.3 配置pipeline脚本 (直接配置或者git获取)
          • 5.7.2.4 编写 jenkinsfile
        • 5.7.3 需要提前配置 wordpress 环境
          • 5.7.3.1 需要 java 环境支持
          • 5.7.3.2 安装LNMP环境
          • 5.7.3.3 配置 nginx 文件
          • 5.7.3.4 启动
        • 5.7.4 构建
      • 5.8 Jenkins流水线自动化发布Java项目
        • 5.8.1 前提
          • 5.8.1.1 安装插件:Maven Integration
          • 5.8.1.2 环境:maven、git、java、tomcat
          • 5.8.1.3 远程拉取配置
        • 5.8.2 配置
          • 5.8.2.1 新建job
          • 5.8.2.2 参数化构建
          • 5.8.2.3 配置git仓库(针对jenkinsfile)
          • 5.8.2.4 编写Jenkinsfile
        • 5.8.3 构建
        • 5.8.4 访问

1、Jenkins介绍

  • Jenkins 功能
    • 持续的软件版本发布/测试项目。
    • 监控外部调用执行的工作。
  • Jenkins 概念
    • Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台。这是一个免费的开源项目,可以处理任何类型的构建或持续集成。集成Jenkins可以用于一些测试和部署技术。Jenkins是一种软件允许持续集成。
  • Jenkins 目的
    • 持续、自动地构建/测试软件项目。
    • 监控软件开放流程,快速问题定位及处理,提提高开发效率。
  • Jenkins 特性
    • 开源的java语言开发持续集成工具,支持CI,CD。
    • 易于安装部署配置:可通过yum安装,或下载war包以及通过docker容器等快速实现安装部署,可方便web界面配置管理。
    • 消息通知及测试报告:集成RSS/E-mail通过RSS发布构建结果或当构建完成时通过e-mail通知,生成JUnit/TestNG测试报告。
    • 分布式构建:支持Jenkins能够让多台计算机一起构建/测试。
    • 文件识别:Jenkins能够跟踪哪次构建生成哪些jar,哪次构建使用哪个版本的jar等。
    • 丰富的插件支持:支持扩展插件,你可以开发适合自己团队使用的工具,如git,svn,maven,docker等。
  • 产品发布流程
    产品设计成型 -> 开发人员开发代码 -> 测试人员测试功能 -> 运维人员发布上线
    • 持续集成(Continuous integration,简称CI)
    • 持续交付(Continuous delivery)
    • 持续部署(continuous deployment)

2、Jenkins CI/CD 流程

说明:这张图稍微更形象一点,上线之前先把代码git到版本仓库,然后通过Jenkins将Java项目通过maven去构建,这是在非容器之前,典型的自动化的一个版本上线流程。那它有哪些问题呢?
如:它的测试环境,预生产环境,测试环境。会存在一定的兼容性问题 (环境之间会有一定的差异)

说明:它这里有一个docker harbor 的镜像仓库,通常会把你的环境打包为一个镜像,通过镜像的方式来部署。

3、部署环境

3.1 环境准备

主机名物理IP
jenkins192.168.200.24
web192.168.200.25
git192.168.200.26

3.2 安装GitLab

官方安装文档:https://about.gitlab.com/installation/#centos-7
GitLab国内源下载地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/

#根据需要下载GitLab安装包
[root@git ~]# wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.3.5-ce.0.el7.x86_64.rpm[root@git ~]# yum -y localinstall gitlab-ce-12.3.5-ce.0.el7.x86_64.rpm 重要说明:
yum localinstall 利用yum安装本地指定的rpm包,好处是自动解决依赖问题

3.3 初始化GitLab

[root@git ~]# gitlab-ctl reconfigure
#以下省略若干。。。#查看gitlab启动状态
[root@git ~]# gitlab-ctl status
run: alertmanager: (pid 3953) 8s; run: log: (pid 3665) 43s
run: gitaly: (pid 3787) 11s; run: log: (pid 3093) 121s
run: gitlab-exporter: (pid 3840) 9s; run: log: (pid 3575) 59s
run: gitlab-workhorse: (pid 3813) 10s; run: log: (pid 3405) 76s
run: grafana: (pid 3978) 7s; run: log: (pid 3764) 20s
run: logrotate: (pid 3434) 70s; run: log: (pid 3460) 69s
run: nginx: (pid 3398) 76s; run: log: (pid 3424) 75s
run: node-exporter: (pid 3831) 10s; run: log: (pid 3520) 65s
run: postgres-exporter: (pid 3968) 7s; run: log: (pid 3695) 39s
run: postgresql: (pid 3176) 116s; run: log: (pid 3188) 113s
run: prometheus: (pid 3932) 8s; run: log: (pid 3633) 49s
run: redis: (pid 3015) 128s; run: log: (pid 3027) 125s
run: redis-exporter: (pid 3886) 9s; run: log: (pid 3607) 53s
run: sidekiq: (pid 3362) 83s; run: log: (pid 3376) 82s
run: unicorn: (pid 3332) 89s; run: log: (pid 3359) 87s

3.4 GitLab中文社区版补丁包安装

GitLab中文社区:https://gitlab.com/xhang/gitlab/tree/11-2-stable-zh

#解压GitLab中文版补丁包
[root@git ~]# tar xf gitlab-12-3-stable-zh.tar.gz#查看系统已经安装的GitLab版本号
[root@git ~]# cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
12.3.5#查看解压后的补丁包版本号
[root@git ~]# cat gitlab-12-3-stable-zh/VERSION 
12.3.5说明:
补丁包版本号和安装的GitLab版本号需要一致
#备份英文版GitLab
[root@git ~]# cp -r /opt/gitlab/embedded/service/gitlab-rails{,.bak}#将中文补丁包的内容覆盖英文版
[root@git ~]# /bin/cp -rf gitlab-12-3-stable-zh/* /opt/gitlab/embedded/service/gitlab-rails/

3.5 修改GitLab配置文件/etc/gitlab/gitlab.rb

我们需要修改GitLab的默认访问域名(因为我们是在内网搭建的GitLab)
GitLab默认的监听端口为80,但是在企业中,这个端口经常被别的服务占用,所以我们还需要更换端口号

[root@git ~]# cp /etc/gitlab/gitlab.rb{,.bak}[root@git ~]# vim /etc/gitlab/gitlab.rb
[root@git ~]# sed -n "13p;1105p" /etc/gitlab/gitlab.rb
external_url 'http://192.168.200.26:88'
nginx['listen_port'] = 88
#重新配置GitLab
[root@git ~]# gitlab-ctl reconfigure
#以下省略若干。。。#重启动GitLab
[root@git ~]# gitlab-ctl restart
ok: run: alertmanager: (pid 5823) 1s
ok: run: gitaly: (pid 5835) 0s
ok: run: gitlab-exporter: (pid 5856) 1s
ok: run: gitlab-workhorse: (pid 5871) 0s
ok: run: grafana: (pid 5885) 0s
ok: run: logrotate: (pid 5901) 1s
ok: run: nginx: (pid 5983) 0s
ok: run: node-exporter: (pid 5992) 1s
ok: run: postgres-exporter: (pid 5999) 0s
ok: run: postgresql: (pid 6010) 1s
ok: run: prometheus: (pid 6019) 0s
ok: run: redis: (pid 6033) 0s
ok: run: redis-exporter: (pid 6037) 1s
ok: run: sidekiq: (pid 6046) 0s
ok: run: unicorn: (pid 6057) 0s

3.6 在宿主机输入 http://192.168.200.26:88 地址就可以访问了

3.7 创建一个项目

3.8 配置GitLab的SSH密钥连接方式

# 在 Web 客户端生成密钥对 
[root@web ~]# ssh-keygen -t rsa
[root@web ~]# ssh-copy-id 192.168.200.26# 公钥内容,复制到GitLab上
[root@web ~]# cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYPbhqszgW9Yv69YYtZAYgIE8zSwJEqQYVuoeLRlXDJ7uqVQxkVx2i4+rhf24w3D2BiZCveEn5tlrU2UexTmmaULGYulv25daFOC6jV/Ll7vQI0JJB5kgvUyI/k3UgYw7P1hWxMTjrzsnSDGdMisOsp0lywzaGNG1BfouNbBLOxhxa6V55LVKmpgPRyU+rc7EjrJ3uL5iYXwS+LJvht9KdJcFQz95F8JmQfe/Vi+UX2HSHXplpwVGGhFM0/Ht2I0Orw8nwsVo6pa4viwQusIuN0zHwHSIIa57E1dxOEvP6NPk2PLYgIQY5pAW6rt+78SvOm5WDmqwHjM16rqM77/hd root@web

3.9 尝试将本地仓库代码推送到私有GitLab

#创建git仓库并初始化
[root@web ~]# mkdir /mycode
[root@web ~]# cd /mycode/
[root@web mycode]# git init
初始化空的 Git 版本库于 /mycode/.git/
# 创建测试文件
[root@web mycode]# echo "web" > index.html
[root@web mycode]# cat index.html 
web# Git全局配置
[root@web mycode]# git config --global user.name "git"
[root@web mycode]# git config --global user.email "git@163.com"# 提交到本地仓库
[root@web mycode]# git add .
[root@web mycode]# git commit -m "web第一次提交测试"# 添加远程GitLab仓库管理
[root@web mycode]# git remote add origin http://192.168.200.26:88/root/app.git
[root@web mycode]# git remote -v
origin	http://192.168.200.26:88/root/app.git (fetch)
origin	http://192.168.200.26:88/root/app.git (push)# 推送本地仓库master分支到远程仓库GitLab上
[root@web mycode]# git push origin master

4、Jenkins 安装配置

jenkins官网以及插件

4.1 安装 java 环境

# 安装 java 环境(最新的Jenkins只执行Java11以上的版本)
[root@jenkins ~]# yum -y install fontconfig java-11-openjdk# 检测java版本
[root@jenkins ~]# java -version
openjdk version "11.0.20" 2023-07-18 LTS
OpenJDK Runtime Environment (Red_Hat-11.0.20.0.8-1.el7_9) (build 11.0.20+8-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-11.0.20.0.8-1.el7_9) (build 11.0.20+8-LTS, mixed mode, sharing)

4.2 安装和配置maven环境

# 解压安装maven
[root@jenkins ~]# tar xf apache-maven-3.5.0-bin.tar.gz -C /usr/local/
[root@jenkins ~]# mv /usr/local/apache-maven-3.5.0 /usr/local/maven# 配置maven环境变量
[root@jenkins ~]# cat >> /etc/profile << EOF
MAVEN_HOME=/usr/local/maven
export PATH=${MAVEN_HOME}/bin:$PATH
EOF[root@jenkins ~]# source /etc/profile[root@jenkins ~]# mvn -v
Apache Maven 3.5.0 (ff8f5e7444045639af65f6095c62210b5713f426; 2017-04-04T03:39:06+08:00)
Maven home: /usr/local/maven
Java version: 11.0.20, vendor: Red Hat, Inc.
Java home: /usr/lib/jvm/java-11-openjdk-11.0.20.0.8-1.el7_9.x86_64
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-1160.83.1.el7.x86_64", arch: "amd64", family: "unix"

4.3 安装 jenkins

# 导入jenkins源
[root@jenkins ~]# wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo# 导入jenkins官方证书
[root@jenkins ~]# rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key# 安装jenkins(安装的是最新的LTS版本)
[root@jenkins ~]# yum install -y jenkins

4.4 配置文件

4.4.1 查询 yum 下载 Jenkins 安装的文件

# 查看yum都安装了哪些东西
[root@jenkins ~]# rpm -ql jenkins
/etc/init.d/jenkins           # 启动文件
/etc/logrotate.d/jenkins      # 日志分割配置文件
/etc/sysconfig/jenkins        # jenkins主配置文件
/usr/bin/jenkins              # 存放war包目录
/usr/lib/systemd/system/jenkins.service    # jenkins启动脚本文件
/usr/sbin/rcjenkins           # 命令
/usr/share/java/jenkins.war   # war 包
/usr/share/jenkins
/usr/share/jenkins/migrate
/var/cache/jenkins            # war包解压目录 jenkins网页代码目录
/var/lib/jenkins              # jenkins 工作目录
/var/log/jenkins              # 日志

4.4.2 修改配置文件

# 复制文件
[root@jenkins ~]# cp /etc/sysconfig/jenkins{,.bak}# 配置文件说明
[root@jenkins ~]# vim /etc/sysconfig/jenkins
[root@jenkins ~]# grep "^[a-Z]" /etc/sysconfig/jenkins
JENKINS_HOME="/var/lib/jenkins"      # jenkins工作目录
JENKINS_JAVA_CMD=""
JENKINS_USER="root"                  # jenkinx启动用户
JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true"
JENKINS_PORT="8080"                  # 端口
JENKINS_LISTEN_ADDRESS=""
JENKINS_HTTPS_PORT=""
JENKINS_HTTPS_KEYSTORE=""
JENKINS_HTTPS_KEYSTORE_PASSWORD=""
JENKINS_HTTPS_LISTEN_ADDRESS=""
JENKINS_DEBUG_LEVEL="5"
JENKINS_ENABLE_ACCESS_LOG="no"
JENKINS_HANDLER_MAX="100"            # 最大连接
JENKINS_HANDLER_IDLE="20"
JENKINS_ARGS=""

4.4.3 启动 jenkins

# 启动 jenkins
[root@jenkins ~]# systemctl start jenkins# 设置开机自启动
[root@jenkins ~]# systemctl enable jenkins

4.4.4 验证安装

[root@jenkins ~]# ps -ef|grep jenkins|grep -v grep
jenkins    2046      1 58 16:32 ?        00:00:55 /usr/bin/java -Djava.awt.headless=true -jar /usr/share/java/jenkins.war --webroot=%C/jenkins/war --httpPort=8080[root@jenkins ~]# netstat -lnutp|grep 8080
tcp6       0      0 :::8080                 :::*                    LISTEN      2046/java

4.5 jenkins配置(web页面)

4.5.1 登录 jenkins web界面

4.5.2 管理员密码获取

[root@jenkins ~]# cat /var/lib/jenkins/secrets/initialAdminPassword
b2f802c1d39d4cb28e1340dcc46e3c44

4.5.3 初始化安装插件

选择默认安装即可

4.5.4 创建第一个管理员用户

4.5.5 url 配置

4.5.6 安装完成

出现如下页面时,表示安装完成

4.5.7 配置 jdk、git、maven

系统管理->全局工具配置

jdk:可以自动安装,但是我们已经安装了,这里写入我们jdk的路径即可

git:

maven:

5、使用Jenkins

5.1 修改默认源,改成国内源

jenkins->系统管理->管理插件->高级 选择升级站点
把:http://updates.jenkins-ci.org/update-center.json
换成:http://mirror.esuni.jp/jenkins/updates/update-center.json

5.2 Jenkins 用户权限管理

5.2.1 用户管理背景

针对开发、运维、测试针对不同角色进行不同权限划分,
基于插件: Role-based Authorization Strategy ,Authorize Project 来实现。

5.2.2 安装用户管理插件

安装该插件:
系统管理->管理插件-可选插件->搜索该插件选中直接安装即可。

5.2.3 开启该插件功能

系统管理->全局安全设置-授权策略->选中该插件功能即可->保存

5.2.4 验证用户管理

关闭用户管理功能来进行实践测试

5.2.4.1 匿名用户不可读写(全局安全配置)

5.2.4.2 开启允许用户注册(全局安全配置)

5.2.4.3 注册一个新用户

5.2.4.4 重新登录新创建的 xiaozhao 用户,但是显示没有任何权限

5.2.5 权限划分

安装 Role-Based Strategy 插件后,系统管理 中多了如图下所示的一个功能,用户权限的划分就是靠他来做的。

5.2.5.1 添加用户

Manage Roles:管理角色,相当于针对角色赋予不同权限,然后在将该角色分配给用户。角色就相当于一个组。其里面又有Global roles(全局)、Project roles(项目)、Slave roles(),来进行不同划分。
默认是有一个admin用户的,是所有权限都有的,默认如图下所示

接下来我们来添加一个角色:user ,给其一个读的权限

5.2.5.2 添加项目
  • roles to add:表示项目角色
  • Pattern:是用来做正则匹配的(匹配的内容是Job(项目名)),比如说根据正则匹配到的项目项目角色就都有权限;
    接下来新建一个 ItemA 项目角色,改项目角色一般给其构建、取消、读取、读取空间权限,一般配置这4个即可

还可以在新建一个 ItemB 项目角色:

  • Slave roles(奴隶角色):节点相关的权限
  • roles to add:表示项目角色
  • Pattern:是用来做正则匹配的(匹配的内容是节点(slavej节点)),比如说根据正则匹配到的项目项目角色就都有权限;
5.2.5.3 给予 xiaozhao 用户分配 user 角色

这样其就有 manage roles 中刚才创建的user角色的权限了。

此时再去看 xiaozhao 用户,已有查看的权限了

5.2.5.4 针对指定用户分配项目角色

比如将 xiaozhao 用户分配有 ItemA 项目角色,这样其就可以有刚才我们创建的 ItemA 项目角色正则匹配到的项目的权限了。

xiaoli 也为其分配一个 ItemB 项目角色

5.2.5.5 创建两个项目分别以A-和B-开头的项目

5.2.5.6 新建视图

开发组

测试组

5.2.5.7 检测项目

此时可以在 xiaozhao 用户这里看到 ItemA 项目角色所匹配到的项目 A-web01

同理 xiaoli 用户这里看到 ItemB 项目角色所匹配到的项目 B-web01

5.3 Jenkins 参数化构建

参数化构建背景:如果只是简单的构建,jenkins自己默认的插件可以做,但是如果我们想要在构建过程中有更多功能,比如说:选择性构建、传参、项目指定变量等等其他功能,基础的参数化构建可以实现一些简单功能,但是要想使用更多功能这时候我们就需要借助参数化构建来实现交互的功能。此处我们来借助以下插件来进行实现:

  • Extended Choice Parameter(更丰富的参数化构建插件)
  • Git Parameter

5.3.1 Extended 插件

5.3.1.1 安装插件

首先还是安装该插件,去管理插件里面进行安装 Extended Choice Parameter

5.3.1.2 项目配置

5.3.1.3 选择安装过的插件

5.3.1.4 进行配置

这里这个branch 我们就相当于给其当做一个变量,然后来为其进行传参。

5.3.1.5 构建选择执行shell进行测试

5.3.1.6 参数化配置已经生效

5.3.1.7 构建 test02

可以发现控制台的输出也是成功了的

5.3.1.8 数据来源选择文件

在jenkins所在服务器进行如下操作:

# 建立一个文件
[root@jenkins ~]# echo "abc=t1,t2,t3,t4" >> /opt/jenkins.property

web 端配置:

进行测试:
构建前:(可以发现也是生效的)

构建后查看结果:(也是成功的)

5.3.2 Git 插件

5.3.2.1 安装插件 Git Parameter

5.3.2.2 进行相关配置

5.3.2.3 配置 git 仓库

当构建时给一个选择列表,这个变量是代表分支。有哪些分支传递给这个变量。

5.3.2.4 进行构建

1、列表中已经有了可选的分支

2、构建成功

3、新建分支增添内容再来验证插件

# 创建新的分支
[root@web mycode]# git branch
* master
[root@web mycode]# git checkout -b test
切换到一个新分支 'test'
[root@web mycode]# git branchmaster
* test# 提交新的分支文件
[root@web mycode]# echo "aaa" > ceshi.ttx
[root@web mycode]# git add .
[root@web mycode]# git commit -m "web第二次提交测试"
[root@web mycode]# git push origin test

4、jenkins 构建查看
可以发现已经有了我们新建的分支

构建成功!!

5.4 Jenkins Master-Slave 架构

  • jenkins的Master-slave分布式架构主要是为了解决jenkins单点构建任务多、负载较高、性能不足的场景。
  • Master/Slave相当于Server和agent的概念。Master提供web接口让用户来管理job和slave,job可以运行在master本机或者被分配到slave上运行构建。一个master(jenkins服务所在机器)可以关联多个slave用来为不同的job或相同的job的不同配置来服务。

5.4.1 安装

前提:slave 所在服务器必须有 java环境

[root@web ~]# which java
/usr/bin/java

jenkins web 端进行操作:系统管理->管理节点->新建节点
进行基础配置,配置选项中的内容是可变的,根据情况来

注意这里需要配置凭据,也就是配置slave所在服务器用户和密码

之后查看日志已经成功了!

5.4.2 配置

在项目 job 中进行配置:可通过标签或者名称进行匹配(标签可在安装时配置)

5.4.3 构建

可以发现控制台的日志,其也是 slave 构建的

之后查看构建完的工作目录,也有预想中的文件。

[root@web ~]# ll /var/lib/jenkins/workspace/A-web01/
总用量 4
-rw-r--r-- 1 root root 4 8月  27 22:00 index.html

这样基本上就实现了借助 jenkins 的 slave 去构建 job了。
目前是在 slave 构建也在 slave 上部署,之后我们可以通过脚本,比如借助 rsync、ansible 等部署在其他服务器上。

5.4.4 扩展

可以为slave服务器在配置时候加上标签,这样也会方便我们选择,用法也不单单局限在一台服务器上,可以让多台 slave 去竞选。

5.5 Jenkins pipeline

5.5.1 概览

在对 jenkins 进行初始化安装时,默认已经安装了 jenkins 的相关插件,如下图所示:

5.5.2 实操

5.5.2.1 新建任务

5.5.2.2 添加项目Git参数化构建

5.5.2.3 编写 pipeline 脚本

可以借助流水线语法去做。

node {def mvnHomestage('git checkout') { // for display purposescheckout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: 'c4f13ee9-bbb1-41cc-9a1c-d72f4dfad6a9', url: 'http://192.168.200.26:88/root/app.git']])}stage('maven Build') {echo "maven build..."}stage('deploy') {echo "deploy..."}stage('test') {echo "test..."}
}

5.5.2.4 构建测试

可以去服务器上验证一下(git checkout)刚才拉取下来的代码:

[root@jenkins ~]# ll /var/lib/jenkins/workspace/pipeline-test/
总用量 4
-rw-r--r-- 1 jenkins jenkins 4 8月  27 22:53 index.html

补充:

  • 可以从代码版本管理仓库中读取 pipeline 脚本(相当于将 pipeline 脚本放在仓库中)我们可以选择git。
  • 首先需要将 pipeline 脚本提交到我们新建的 git仓库中(步骤再此忽略。)

5.6 Jenkins 构建邮件状态通知

5.6.1 前提

前提:服务器开启邮箱服务

[root@jenkins ~]# systemctl status postfix | grep activeActive: active (running) since 二 2023-08-22 16:14:29 CST; 5 days ago

5.6.2 基础配置

需要安装一个插件:Email Extension Plugin

进行配置:系统管理->系统设置->相关配置如下图:

可以在此处进行测试发送!检验配置是否正确

查看邮箱

5.6.3 配置到项目中

在项目的配置中选择构建后操作,选择我们对应的插件

填写发件人信息

配置构建成功发送邮件

控制台也有邮件发送成功输出

检查实际是否接收到邮件

5.7 Jenkins 流水线自动化发布PHP项目

5.7.1 前提

环境为:lnmp
PHP项目:wordpress(此处我们下载一个wordpress的源码。将其模拟为我们的代码上传到我们的git仓库)

# 创建新的分支
[root@web mycode]# git checkout -b lnmp
切换到一个新分支 'lnmp'
[root@web mycode]# git branch
* lnmpmastertest# 下载wordpress的源码
[root@web mycode]# wget https://cn.wordpress.org/wordpress-5.2.1-zh_CN.tar.gz -O ~/wordpress-5.2.1-zh_CN.tar.gz
[root@web mycode]# tar xf ~/wordpress-5.2.1-zh_CN.tar.gz -C ~/
[root@web mycode]# mv ~/wordpress/* .
[root@web mycode]# echo "ok" > status.html# 提交到本地仓库
[root@web mycode]# git add --all
[root@web mycode]# git commit -m "web第三次提交测试"
[root@web mycode]# git push origin lnmp

部署节点: node 节点需要在系统管理中配置节点

5.7.2 配置

5.7.2.1 创建job

5.7.2.2 参数化构建

5.7.2.3 配置pipeline脚本 (直接配置或者git获取)

直接配置

git获取

5.7.2.4 编写 jenkinsfile
编写 jenkinsfile 源码文件:jenkinsfile-PHP
[root@web mycode]# vim jenkinsfile-PHP
[root@web mycode]# cat jenkinsfile-PHP
node ("slave") {stage('git checkout') {checkout scmGit(branches: [[name: '*/lnmp']], extensions: [], userRemoteConfigs: [[credentialsId: 'c4f13ee9-bbb1-41cc-9a1c-d72f4dfad6a9', url: 'http://192.168.200.26:88/root/app.git']])}stage('code copy') {sh '''rm -rf ${WORKSPACE}/.gitmv /usr/share/nginx/html/wp.com /data/backup/wp.com-$(date +"%F_%T")cp -rf ${WORKSPACE} /usr/share/nginx/html/wp.com'''}stage('test') {sh "curl http://192.168.200.25/status.html"}
}# 提交到本地仓库
[root@web mycode]# git add .
[root@web mycode]# git commit -m "web第四次提交测试"
[root@web mycode]# git push origin lnmp

下面为带解释版,但不可以使用,部分注释会造成问题

node ("slave") {                  # 绑定到该节点去执行stage('git checkout') {checkout scmGit(branches: [[name: '*/lnmp']], extensions: [], userRemoteConfigs: [[credentialsId: 'c4f13ee9-bbb1-41cc-9a1c-d72f4dfad6a9', url: 'http://192.168.200.26:88/root/app.git']])}# 拉代码# $class: 'GitSCM' git插件获取代码的工具# branches 分支名称# doGenerateSubmoduleConfigurations 是否包含子模块配置# extensions 扩展功能# submoduleCfg  子模块配置# userRemoteConfigs 远程用户配置(仓库地址)stage('code copy') {                           # 复制代码sh '''rm -rf ${WORKSPACE}/.git            # 删除拉下来的项目的.git敏感文件mkdir -p /data/backup/web-$(date +"%F")   # 创建备份目录mv /usr/share/nginx/html/wp.com /data/backup/wp.com-$(date +"%F_%T")   # 备份旧文件cp -rf ${WORKSPACE} /usr/share/nginx/html/wp.com'''                 # 新文件复制到站点目录}stage('test') {               # 测试sh "curl http://192.168.200.25/status.html"}
}

5.7.3 需要提前配置 wordpress 环境

5.7.3.1 需要 java 环境支持
[root@web ~]# which java
/usr/bin/java
5.7.3.2 安装LNMP环境
[root@web ~]# yum -y install epel-release nginx php-fpm php-mysql
5.7.3.3 配置 nginx 文件
[root@web ~]# sed -n "36p;42p" /etc/nginx/nginx.confinclude /etc/nginx/conf.d/*.conf;           # include了一个配置文件目录root         /usr/share/nginx/html;     # 默认的网页目录# 因此我们增加一个server配置文件即可
[root@web ~]# vim /etc/nginx/conf.d/wp.conf
[root@web ~]# cat /etc/nginx/conf.d/wp.conf
server {listen 80;server_name wp.test.com;root    /usr/share/nginx/html/wp.com;location / {index index.php index.html;}location ~\.php {fastcgi_index index.php;fastcgi_pass 127.0.0.1:9000;include fastcgi.conf;}
}# 创建 wordpress 网页目录
[root@web ~]# mkdir -p /usr/share/nginx/html/wp.com
5.7.3.4 启动
[root@web ~]# systemctl start nginx
[root@web ~]# systemctl start php-fpm

5.7.4 构建

构建概览:

控制台输出详情:

可以看到每一步的执行详情,最后也是成功的!!!
此外我们可以查看服务器及网页实际体验效果进行验证。http://192.168.200.25

5.8 Jenkins流水线自动化发布Java项目

5.8.1 前提

5.8.1.1 安装插件:Maven Integration

5.8.1.2 环境:maven、git、java、tomcat
[root@web ~]# which git
/usr/bin/git
[root@web ~]# which java
/usr/bin/java
[root@web ~]# which mvn
/usr/local/maven/bin/mvn
[root@web ~]# tar xf apache-tomcat-8.0.27.tar.gz -C /usr/local/
[root@web ~]# mv /usr/local/apache-tomcat-8.0.27 /usr/local/tomcat
[root@web ~]# rm -rf /usr/local/tomcat/webapps/*
# 部署 tomcat 环境变量
[root@web ~]# cat >> /etc/profile << EOF
export TOMCAT_HOME=/usr/local/tomcat
EOF
[root@web ~]# source /etc/profile
5.8.1.3 远程拉取配置

用的博客系统代码: git clone https://github.com/88250/solo.git

# 创建新的分支
[root@web mycode]# git checkout -b solo
切换到一个新分支 'solo'
[root@web mycode]# git branchlnmpmaster
* solotest# 下载 solo 源码
[root@web mycode]# wget https://github.com/88250/solo/archive/refs/heads/master.zip# 解压压缩包
[root@web mycode]# unzip master.zip
[root@web mycode]# mv solo-master/* .
[root@web mycode]# rm -rf solo-master master.zip # 修改指定的域名
[root@web mycode]# vim src/main/resources/latke.properties
[root@web mycode]# sed -n "21p" src/main/resources/latke.properties
serverHost=192.168.200.25[root@web mycode]# echo "ok" > status.html# 提交到本地仓库
[root@web mycode]# git add --all
[root@web mycode]# git commit -m "web第四次提交测试"
[root@web mycode]# git push origin solo

部署节点: node 节点需要在系统管理中配置节点

5.8.2 配置

5.8.2.1 新建job

5.8.2.2 参数化构建

5.8.2.3 配置git仓库(针对jenkinsfile)

5.8.2.4 编写Jenkinsfile

编写 jenkinsfile 源码文件:Jenkinsfile-JAVA

[root@web mycode]# vim Jenkinsfile-JAVA
[root@web mycode]# cat Jenkinsfile-JAVA
node ("slave") {stage('git checkout') {checkout scmGit(branches: [[name: '*/solo']], extensions: [], userRemoteConfigs: [[credentialsId: 'c4f13ee9-bbb1-41cc-9a1c-d72f4dfad6a9', url: 'http://192.168.200.26:88/root/app.git']])}stage('maven build') {sh '''export JAVA_HOME=/usr/local/jdk/usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true'''}stage('deploy') {sh '''JENKINS_NODE_COOKIE=dontkillmeexport JAVA_HOME=/usr/local/jdkTOMCAT_HOME=/usr/local/tomcatWWWROOT=$TOMCAT_HOME/webapps/ROOT[ -d /data/backup ] || mkdir -p /data/backupif [ -d $WWWROOT ];thenmv $WWWROOT /data/backup/tomcat-$(date +"%F_%T")fiunzip ${WORKSPACE}/target/*.war -d $WWWROOTPID=$(ps -ef |grep tomcat |grep -v "grep" |awk '{print $2}')[ -n "$PID" ] && kill -9 $PIDnohup $TOMCAT_HOME/bin/startup.sh &'''}stage('test') {echo "susses"}
}# 提交到本地仓库
[root@web mycode]# git add --all
[root@web mycode]# git commit -m "web第五次提交测试"
[root@web mycode]# git push origin solo

下面为带解释版,但不可以使用,部分注释会造成问题

node ("slave") {			  # 绑定到该节点构建stage('git checkout') {    # 拉代码checkout scmGit(branches: [[name: '*/solo']], extensions: [], userRemoteConfigs: [[credentialsId: 'c4f13ee9-bbb1-41cc-9a1c-d72f4dfad6a9', url: 'http://192.168.200.26:88/root/app.git']])}stage('maven build') {sh '''export JAVA_HOME=/usr/local/jdk		# 在指定java环境变量								/usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true     # 构建maven包 clean package表示构建之前会清理之前构建的包,-Dmaven.test.skip=true表示跳过单元测试'''}stage('deploy') {sh '''JENKINS_NODE_COOKIE=dontkillme     # 解决jenkins会在构建结束杀掉衍生子进程问题export JAVA_HOME=/usr/local/jdkTOMCAT_HOME=/usr/local/tomcatWWWROOT=$TOMCAT_HOME/webapps/ROOT[ -d /data/backup ] || mkdir -p /data/backupif [ -d $WWWROOT ];thenmv $WWWROOT /data/backup/tomcat-$(date +"%F_%T")fiunzip ${WORKSPACE}/target/*.war -d $WWWROOT			# 项目包解压到站点目录PID=$(ps -ef |grep tomcat |grep -v "grep" |awk '{print $2}')[ -n "$PID" ] && kill -9 $PIDnohup $TOMCAT_HOME/bin/startup.sh &'''}stage('test') {echo "susses"}
}

5.8.3 构建

构建概览:

控制台输出详情:

5.8.4 访问

http://192.168.200.25:8080/

相关文章:

Jenkins详解(三)

Jenkins详解(三) 目录 Jenkins详解(三) 1、Jenkins介绍2、Jenkins CI/CD 流程3、部署环境 3.1 环境准备3.2 安装GitLab3.3 初始化GitLab3.4 GitLab中文社区版补丁包安装3.5 修改GitLab配置文件/etc/gitlab/gitlab.rb3.6 在宿主机输入 http://192.168.200.26:88 地址就可以访问了…...

【真题解析】系统集成项目管理工程师 2023 年上半年真题卷(综合知识)

本文为系统集成项目管理工程师考试(软考) 2023 年上半年真题(全国卷),包含答案与详细解析。考试共分为两科,成绩均 ≥45 即可通过考试: 综合知识(选择题 75 道,75分)案例分析(问答题 4 道,75分)综合知识(选择题*75)1-10 题11-20 题21-30 题31-40 题41-50 题51-60 …...

开始MySQL之路——MySQL存储引擎概念

一、存储引擎概念 MySQL数据库和大多数的数据库不同, MySQL数据库中有一个存储引擎的概念, 针对不同的存储需求可以选择最优的存储引擎。 ​ 存储引擎就是存储数据&#xff0c;建立索引&#xff0c;更新查询数据等等技术的实现方式 。存储引擎是基于表的&#xff0c;而不是基…...

ant-design 设置Form.Item中的input框的值的方法

ant-design 设置Form.Item中的input中的value值是不知道什么原因是无效的&#xff0c;所以有以下两种方法设置&#xff1a; 1.可以通过 initialValues 属性来为表单设置默认值。具体使用方法如下&#xff1a; 在表单最外层的 Form 组件上加入 initialValues 属性&#xff0c;…...

CS420 课程笔记 P6 - 游戏逆向中的虚拟内存

文章目录 IntroVirtual memoryExample!Static example Intro 在上个视频中&#xff0c;我们知道有些地址在你重进游戏时就会无效&#xff0c;有的有时有效&#xff0c;我们需要了解称为虚拟内存的东西 记住这些信息&#xff1a;当你双击打开 Squally.exe 游戏时&#xff0c;系…...

公信力不是儿戏:政府与非营利组织如何利用爱校对提升信息质量

公信力是政府和非营利组织成功的基础&#xff0c;而这种公信力大多来源于对外发布的信息的准确性和可靠性。在这个方面&#xff0c;“爱校对”展现了它的强大能力和实用性。以下我们将具体探讨这两种组织如何通过使用爱校对来提升他们的信息质量。 政府&#xff1a;公开与透明&…...

Linux内核源码分析 (B.1)内核内存布局和堆管理

Linux内核源码分析 (B.1)内核内存布局和堆管理 文章目录 Linux内核源码分析 (B.1)内核内存布局和堆管理一、Linux内核内存布局二、堆管理 一、Linux内核内存布局 64位Linux一般使用48位来表示虚拟地址空间&#xff0c;45位表示物理地址。通过命令&#xff1a;cat/proc/cpuinfo。…...

Python---函数

函数定义&#xff1a; """ def 函数名(传入参数):函数体return 返回值 """ 函数调用&#xff1a; """ 函数名(传入参数) """ 例子&#xff1a; # 不带参 def check():print("欢迎光临\n请进") che…...

Myvatis关联关系映射与表对象之间的关系

目录 一、关联关系映射 1.1 一对一 1.2 一对多 1.3 多对多 二、处理关联关系的方式 2.1 嵌套查询 2.2 嵌套结果 三、一对一关联映射 3.1 建表 ​编辑 3.2 配置文件 3.3 代码生成 3.4 编写测试 四、一对多关联映射 五、多对多关联映射 六、小结 一、关联关系映射 …...

算法通关村第十四关:黄金挑战-数据流的中位数

黄金挑战-数据流的中位数 1.数据流中中位数的问题 LeetCode295 https://leetcode.cn/problems/find-median-from-data-stream/ 思路分析 中位数的问题&#xff0c;我们一般都可以用 大顶堆小顶堆 来求解 小顶堆&#xff08;minHeap&#xff09;&#xff1a;存储所有元素中…...

【2023集创赛】国家集创中心杯三等奖:不对称轻失配运算放大器

本文为2023年第七届全国大学生集成电路创新创业大赛&#xff08;“集创赛”&#xff09;国家集创中心杯三等奖作品分享&#xff0c;参加极术社区的【有奖征集】分享你的2023集创赛作品&#xff0c;秀出作品风采&#xff0c;分享2023集创赛作品扩大影响力&#xff0c;更有丰富电…...

手写Mybatis:第18章-一级缓存

文章目录 一、目标&#xff1a;一级缓存二、设计&#xff1a;一级缓存三、实现&#xff1a;一级缓存3.1 工程结构3.2 一级缓存类图3.3 一级缓存实现3.3.1 定义缓存接口3.3.2 实现缓存接口3.3.3 创建缓存KEY3.3.4 NULL值缓存key 3.4 定义缓存机制、占位符和修改配置文件3.4.1 定…...

哈夫曼编码实现文件的压缩和解压

程序示例精选 哈夫曼编码实现文件的压缩和解压 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《哈夫曼编码实现文件的压缩和解压》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0…...

解决六大痛点促进企业更好使用生成式AI,亚马逊云科技顾凡采访分享可用方案

亚马逊云科技大中华区战略业务发展部总经理顾凡在接受21世纪经济报道记者专访时表示&#xff0c;生成式人工智能将从四个方面为企业带来机遇&#xff1a;第一是创造全新的客户体验&#xff1b;第二是提高企业内部员工的生产力&#xff1b;第三是帮助企业提升业务运营效率&#…...

Qt 定时器放在线程中执行,支持随时开始和停止定时器。

前言&#xff1a;因为项目需要定时检查网络中设备是否能连通&#xff0c;需要定时去做ping操作&#xff0c;若是网络不通&#xff0c;则ping花费时间比较久&#xff08;局域网大概4秒钟才能结束&#xff0c;当然如果设置超时时间啥的&#xff0c;也能很快返回&#xff0c;就是会…...

java 过滤器 接口(API)验证入参,验签(sign) Demo

java 过滤器 接口&#xff08;API&#xff09;验证入参&#xff0c;验签&#xff08;sign&#xff09; Demo 一、思路 1、配置yml文件; 2、创建加载配置文件类; 3、继承 OncePerRequestFilter 重写方法 doFilterInternal; 4、注册自定义过滤器; 二、步骤 1、配置yml文件; ###系…...

独家!微信正在灰测一款全新消金产品

来源 | 镭射财经&#xff08;leishecaijing&#xff09; 「镭射财经」独家获悉&#xff0c;微信将推出一款名为“微信分期”的新消费信贷产品&#xff0c;目前该产品正处于小范围灰测阶段&#xff0c;还未正式上线。上线后&#xff0c;微信将运营微信分付和微信分期两款自营消…...

阿秀C++笔记-学习记录

81.C中的组合和继承相比的优缺点 在C中组合一对象系用描述对象包对象系组一个拥对象例其变合类的含的现。这的量类当有员被创建。 以下一个示例&#xff0c;展示了在C中如何实现组合关系&#xff1a; class Engine {// Engine class definition... };class Car {Engine engi…...

前端入门到入土?

文章目录 前言http和https的区别&#xff0c;https加密的原理是&#xff1f;区别https的加密原理 TCP为什么要三次握手&#xff1f;proxy代理的原理&#xff1f;内存泄漏&#xff1f;什么是内存泄漏&#xff1f;为什么会有内存泄漏&#xff1f;内存泄漏的情况&#xff1f;如何防…...

架构设计基础设施保障IaaS之网络

目录 1 DNS运用1.1 DNS功能作用1.2 DNS配置实践 2 DNS生产最佳实践方案2.1 全球加速功能2.2 不同运营商的加速方案2.3 全球业务高可用方案2.4 跨地域负载均衡 3 DNS域名劫持解决方案4 CDN剖析4.1 CDN原理4.2 缓存过期配置处理流程4.3 缓存配置规则 5 CDN运用6 CDN最佳实践方案6…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...

边缘计算网关提升水产养殖尾水处理的远程运维效率

一、项目背景 随着水产养殖行业的快速发展&#xff0c;养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下&#xff0c;而且难以实现精准监控和管理。为了提升尾水处理的效果和效率&#xff0c;同时降低人力成本&#xff0c;某大型水产养殖企业决定…...

算法刷题-回溯

今天给大家分享的还是一道关于dfs回溯的问题&#xff0c;对于这类问题大家还是要多刷和总结&#xff0c;总体难度还是偏大。 对于回溯问题有几个关键点&#xff1a; 1.首先对于这类回溯可以节点可以随机选择的问题&#xff0c;要做mian函数中循环调用dfs&#xff08;i&#x…...