引言

Devops能干嘛?

提高产品质量
1 自动化测试
2 持续集成
3 代码质量管理工具
4 程序员鼓励师
2、Devops如何实现
既然这么好?为什么有些公司没有
设计架构规划‐代码的存储‐构建‐测试、预生产、部署、监控

1、Devops(模拟测试环境)

服务器 虚拟机 纯干净的系统
IP 主机名 配置
10.0.0.200 Gitlab 2核4G 50G硬盘
10.0.0.201 Jenkins 1核2G 50G硬盘
10.0.0.202 Nexus 1核2G 50G硬盘
10.0.0.203 Sonar 1核2G 50G硬盘
10.0.0.7 Web 1核1G 50G硬盘

2、Git版本控制系统

1、版本控制系统简介
vcs `version control system`
版本控制系统是一种记录一个或若干个文件内容变化,以便将来查阅特定版本内容情况的系统
记录文件的所有历史变化
随时可恢复到任何一个历史状态
多人协作开发
#类似于虚拟机的快照
2、常见版本管理工具
1.SVN
2.git
页面版的代码仓库
1.github 全球使用最多的代码仓库
2.gitlab 全球使用最多的私有代码仓库
3.gitee 码云 中国使用最多的代码仓库

3、git使用
1、配置当前代码仓库的使用角色的信息
git环境Kylin v10 SP3
[root@oldboy:~]#git --version
git version 2.27.0
[root@xxxx ~/count_bash]#git config --global user.name "lizhenya"
[root@xxxx ~/count_bash]#git config --global user.email "lizhenya@mail.com"
[root@xxxx ~/count_bash]#git config --global color.ui true
[root@oldboy:~]#git config --list
user.name=lizhenya
user.email=lizhenya@mail.com
color.ui=true

#实际写入到.gitconfig文件
[root@xxxx ~]#cat .gitconfig 
[user]
    email = lizhenya@mail.com
    name = lizhenya
[color]
    ui = true
2、初始化仓库
#创建代码目录
[root@git ~]#mkdir git_data
[root@git ~]#cd git_data/
#git初始化命令,初始化后生成隐藏代码仓库.git
[root@git ~/git_data]#git init
Initialized empty Git repository in /root/git_data/.git/
[root@git ~/git_data]#ll -a
total 0
drwxr-xr-x 3 root root  18 May 28 21:42 .
dr-xr-x--- 5 root root 207 May 28 21:41 ..
drwxr-xr-x 7 root root 119 May 28 21:42 .git
# 查看隐藏的代码仓库
[root@git ~/git_data]#ll .git/
total 12
drwxr-xr-x 2 root root   6 May 28 21:42 branches     # 分支
-rw-r--r-- 1 root root  92 May 28 21:42 config       # 配置文件
-rw-r--r-- 1 root root  73 May 28 21:42 description  # 描述 
-rw-r--r-- 1 root root  23 May 28 21:42 HEAD         # 头部
drwxr-xr-x 2 root root 332 May 28 21:42 hooks        # 勾子
drwxr-xr-x 2 root root  21 May 28 21:42 info
drwxr-xr-x 4 root root  30 May 28 21:42 objects      # 项目 代码放此目录但是不是明文的HASH
drwxr-xr-x 4 root root  31 May 28 21:42 refs
drwxr-xr-x 4 root root 31 Sep 27 09:23  index        # 暂存区文件,只有代码提交到暂存区才有
3、git区域名称

工作目录: 进入git_data目录 当前的位置称为工作目录 类似车间工人
暂存区域: 临时存放代码的问题 类似质检车间 有问题可以返回,没有问题可以保存到仓库,类似于反悔的区域
本地仓库: 存储代码的位置类似工厂仓库
开发在工作目录写代码--->提交到暂存区域---->提交到本地仓库--->代码才真正的被管理。每次走当前这个流程相当于虚拟机做了一个快照的动作
4、git常用命令
#增

将文件保存到本地仓库的流程
1.创建文件
[root@git ~/git_data]#touch a.txt
# 查看当前状态
[root@git ~/git_data]#git status
On branch master  # 当前位于主干

No commits yet    # 没有可提交的操作

Untracked files:  # 未跟踪的文件
  (use "git add <file>..." to include in what will be committed)
    a.txt         # 文件是红色

nothing added to commit but untracked files present (use "git add" to track)

2.工作区提交到暂存区

[root@git ~/git_data]#git add a.txt
[root@git ~/git_data]#git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   a.txt  # 文件被提交到暂存区,变成了绿色

#多出了一个index文件
[root@git ~/git_data]#ll .git
total 16
drwxr-xr-x 2 root root   6 May 28 21:42 branches
-rw-r--r-- 1 root root  92 May 28 21:42 config
-rw-r--r-- 1 root root  73 May 28 21:42 description
-rw-r--r-- 1 root root  23 May 28 21:42 HEAD
drwxr-xr-x 2 root root 332 May 28 21:42 hooks
-rw-r--r-- 1 root root 104 May 28 21:54 index
drwxr-xr-x 2 root root  21 May 28 21:42 info
drwxr-xr-x 5 root root  40 May 28 21:54 objects
drwxr-xr-x 4 root root  31 May 28 21:42 refs

3.将暂存区的内容提交到本地仓库,类似快照

注意: 只要执行一次commit 就相当于做了一个快照
[root@git ~/git_data]#git commit -m "newfile a.txt"
[master (root-commit) 1150b18] newfile a.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
#提交完之后要成为下面的状态,干净的工作目录
[root@git ~/git_data]#git status
On branch master
nothing to commit, working tree clean

#又创建新的文件,相当于第二次快照里面有a.txt跟b.txt
[root@git ~/git_data]#touch b.txt
[root@git ~/git_data]#git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
    b.txt

nothing added to commit but untracked files present (use "git add" to track)
[root@git ~/git_data]#git add b.txt
[root@git ~/git_data]#git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    new file:   b.txt

[root@git ~/git_data]#git commit -m "newfile ab.txt"
[master 2ce0877] newfile ab.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 b.txt
[root@git ~/git_data]#ll
total 0
-rw-r--r-- 1 root root 0 May 28 21:52 a.txt
-rw-r--r-- 1 root root 0 May 28 22:02 b.txt


#删

git删除文件使用 git rm -f
1. 删除
[root@git ~/git_data]#git rm -f b.txt 
rm 'b.txt'

[root@git ~/git_data]#git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    deleted:    b.txt

no changes added to commit (use "git add" and/or "git commit -a")

2.把操作提交到暂存区

[root@git ~/git_data]#git add b.txt
[root@git ~/git_data]#git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    deleted:    b.txt

3.将暂存区的内容提交到本地仓库,快照

[root@git ~/git_data]#git commit -m "newfile"
[master 3ca1df7] newfile
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 a.txt

#如果不小心误删除了工作目录的文件可以恢复git恢复工作目录的文件
[root@oldboy:git_data]#rm -f a.txt
[root@oldboy:git_data]#git restore a.txt
[root@oldboy:git_data]#ll
total 0
-rw-r--r-- 1 root root 0 Sep 27 09:55
a.txt

# 改
git修改文件
[root@oldboy:git_data]#echo aaaa >> b.txt
[root@oldboy:git_data]#git add .
[root@oldboy:git_data]#git commit -m "modifiled b.txt >>aaaa"
[master 21ed94f] modifiled b.t	xt >>aaaa
1 file changed, 1 insertion(+)

查看历史提交日志
git log --oneline
git log
commit 28736231685dd9f4dfb9e793615f933b2dd674dd (HEAD -> master)
Author: lizhenya <lizhenya@mail.com>
Date:   Wed May 28 22:33:44 2025 +0800

    modifiled d.txt

commit 48078b4b712e387eb0c227076f78e3d19f7f71ec
Author: lizhenya <lizhenya@mail.com>
Date:   Wed May 28 22:32:08 2025 +0800

    delete c.txt

工作区的d.txt添加内容

[root@git ~/git_data]#echo dddddddd >> d.txt
[root@git ~/git_data]#ll
total 4
-rw-r--r-- 1 root root 13 May 28 22:44 d.txt
#比较工作区跟暂存区的区别
[root@git ~/git_data]#git diff d.txt
diff --git a/d.txt b/d.txt
index 1d60b70..02eda96 100644
--- a/d.txt
+++ b/d.txt
@@ -1 +1,2 @@
 ddd
+dddddddd  # 多的内容
#提交到暂存区,内容一样
[root@git ~/git_data]#git add .
[root@git ~/git_data]#git diff

#比较暂存区和本地仓库的区别

#因为没提交,所以一样

[root@git ~/git_data]#git diff --cached d.txt
#提交后,内容不一样
[root@git ~/git_data]#git diff --cached d.txt
diff --git a/d.txt b/d.txt
index 1d60b70..02eda96 100644
--- a/d.txt
+++ b/d.txt
@@ -1 +1,2 @@
 ddd
+dddddddd
#提交到本地仓库,一样
[root@git ~/git_data]#git commit -m "v1.5"
[master da5d4f0] v1.5
 1 file changed, 1 insertion(+)
[root@git ~/git_data]#git diff --cached d.txt

# git diff 比对的工作目录和暂存区的不同
# git diff --cached 比对的是暂存区和本地仓库的不同

版本回滚

# git log只能看当前版本及之前版本的信息,无法查看所有的
[root@oldboy ~/git_data]#git log --oneline
2cfee95 (HEAD -> master) delfile
4cc392a newfile b.txt
8984112 newfile a.txt

# 回滚到4cc392a
[root@oldboy ~/git_data]#git reset --hard 4cc392a
HEAD is now at 4cc392a newfile b.txt
[root@oldboy ~/git_data]#ll
total 0
-rw-r--r-- 1 root root 0 May 28 23:18 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt
[root@oldboy ~/git_data]#git log --oneline
4cc392a (HEAD -> master) newfile b.txt
8984112 newfile a.txt

#reflog 查看所有的历史提交
[root@oldboy ~/git_data]#git reflog
4cc392a (HEAD -> master) HEAD@{0}: reset: moving to 4cc392a
2cfee95 HEAD@{1}: commit: delfile
4cc392a (HEAD -> master) HEAD@{2}: commit: newfile b.txt
8984112 HEAD@{3}: commit (initial): newfile a.txt
5、git分支

拉取复制主分支代码到子分支进行测试、开发,之后进行合并

查看当前工作目录状态

[root@oldboy ~/git_data]#git status
On branch master
nothing to commit, working tree clean
# 查看当前所在分支
[root@oldboy ~/git_data]#git branch
* master
# 创建testing分支
[root@oldboy ~/git_data]#git branch testing
# 查看当前所在
[root@oldboy ~/git_data]#git branch
* master
  testing
# 切换到testing分支
[root@oldboy ~/git_data]#git checkout testing
Switched to branch 'testing'
# 查看当前所在 
[root@oldboy ~/git_data]#git branch
  master
* testing


# 创建新的功能c.txt

[root@oldboy ~/git_data]#touch c.txt
[root@oldboy ~/git_data]#git add c.txt
[root@oldboy ~/git_data]#git commit -m "new files c.txt"
[testing 70bc6a9] new files c.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 c.txt
[root@oldboy ~/git_data]#git status
On branch testing
nothing to commit, working tree clean
[root@oldboy ~/git_data]#ll
total 0
-rw-r--r-- 1 root root 0 May 28 23:18 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt
-rw-r--r-- 1 root root 0 May 28 23:42 c.txt

# 切换到主分支

[root@oldboy ~/git_data]#git checkout master
Switched to branch 'master'
[root@oldboy ~/git_data]#git branch
* master
  testing
[root@oldboy ~/git_data]#git status
On branch master
nothing to commit, working tree clean
# 因为没同步testing分支,所以没有新文件
[root@oldboy ~/git_data]#ll
total 0
-rw-r--r-- 1 root root 0 May 28 23:18 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt

# 将testing中的代码合并到master分支

[root@oldboy ~/git_data]#git merge testing
Updating 4cc392a..70bc6a9
Fast-forward
 c.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 c.txt
[root@oldboy ~/git_data]#ll
total 0
-rw-r--r-- 1 root root 0 May 28 23:18 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt
-rw-r--r-- 1 root root 0 May 28 23:47 c.txt

# 合并后删除testing分支,因为开发有很多,如果都提交了功能,那么当前分支落后于主分支会提交失败,代码不同步
[root@oldboy ~/git_data]#git branch
* master
  testing
[root@oldboy ~/git_data]#git branch -d testing
Deleted branch testing (was 70bc6a9).
[root@oldboy ~/git_data]#git branch
* master
6、分支冲突

1.主分支新增内容

# 查看当前分支
[root@oldboy ~/git_data]#git branch
* master
# 创建分支
[root@oldboy ~/git_data]#git branch testing
[root@oldboy ~/git_data]#git branch
* master
  testing
[root@oldboy ~/git_data]#ll
total 0
-rw-r--r-- 1 root root 0 May 28 23:18 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt
-rw-r--r-- 1 root root 0 May 28 23:47 c.txt
# 追加内容
[root@oldboy ~/git_data]#echo "111" > a.txt
[root@oldboy ~/git_data]#cat a.txt 
111
[root@oldboy ~/git_data]#git add a.txt
# 提交到本地仓库
[root@oldboy ~/git_data]#git commit -m "modifle a.txt 111"
[master 627f9be] modifle a.txt 111
 1 file changed, 1 insertion(+)
[root@oldboy ~/git_data]#ll
total 4
-rw-r--r-- 1 root root 4 May 29 08:43 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt
-rw-r--r-- 1 root root 0 May 28 23:47 c.txt
[root@oldboy ~/git_data]#git status
On branch master
nothing to commit, working tree clean

2.testing分支增加内容

# 切换testing分支
[root@oldboy ~/git_data]#git checkout testing
Switched to branch 'testing'
[root@oldboy ~/git_data]#git branch
  master
* testing
# 追加内容
[root@oldboy ~/git_data]#echo "222" > a.txt
[root@oldboy ~/git_data]#cat a.txt 
222
[root@oldboy ~/git_data]#git add a.txt
[root@oldboy ~/git_data]#git commit -m "modifl a.txt 222"
[testing 2faee16] modifl a.txt 222
 1 file changed, 1 insertion(+)
[root@oldboy ~/git_data]#ll
total 4
-rw-r--r-- 1 root root 4 May 29 08:47 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt
-rw-r--r-- 1 root root 0 May 28 23:47 c.txt
[root@oldboy ~/git_data]#git status
On branch testing
nothing to commit, working tree clean

3.切换主分支合并

# 切换主分支
[root@oldboy ~/git_data]#git checkout master
Switched to branch 'master'
[root@oldboy ~/git_data]#git branch
* master
  testing
[root@oldboy ~/git_data]#cat a.txt 
111
# 合并testing分支,失败,显示冲突了
[root@oldboy ~/git_data]#git merge testing
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.

# 查看冲突文件
[root@oldboy ~/git_data]#cat a.txt 
> HEAD
111
=======
222
< testing

# vim进去手动解决冲突
[root@oldboy ~/git_data]#cat a.txt 
111
222

# 提交到仓库,解决
[root@oldboy ~/git_data]#git add .
[root@oldboy ~/git_data]#git commit -m "merge testing"
[master 7284362] merge testing
[root@oldboy ~/git_data]#git status
On branch master
nothing to commit, working tree clean
[root@oldboy ~/git_data]#ll
total 4
-rw-r--r-- 1 root root 8 May 29 08:52 a.txt
-rw-r--r-- 1 root root 0 May 28 23:14 b.txt
-rw-r--r-- 1 root root 0 May 28 23:47 c.txt
[root@oldboy ~/git_data]#cat a.txt 
111
222
7、git标签
标签也是指向了一次commit提交,是一个里程碑式的标签,回滚打标签直接加标签号,不需要加唯一字符串不好记
标签即为版本号

[root@oldboy ~/git_data]#git log --oneline
7284362 (HEAD -> master) merge testing
2faee16 modifl a.txt 222
627f9be modifle a.txt 111
70bc6a9 new files c.txt
4cc392a newfile b.txt
8984112 newfile a.txt

# 给最早的一个hahs值打tag
[root@oldboy ~/git_data]#git tag -a v1.0 8984112 -m "v1.0稳定版"
[root@oldboy ~/git_data]#git tag -a v1.1 7284362 -m "v1.0最新版"

# 查看标签
[root@oldboy ~/git_data]#git tag
v1.0
v1.1

# 查看tag的详细信息
[root@oldboy ~/git_data]#git show v1.0
tag v1.0
Tagger: lizhenya <lizhenya@mail.com>
Date:   Thu May 29 09:06:07 2025 +0800

v1.0稳定版

commit 89841125cfbf9d55e1cd2886fd8f188f93dcb87a (tag: v1.0)
Author: lizhenya <lizhenya@mail.com>
Date:   Wed May 28 23:14:27 2025 +0800

    newfile a.txt

diff --git a/a.txt b/a.txt
new file mode 100644
index 0000000..e69de29

# 通过tag版本回滚代码
[root@oldboy ~/git_data]#git reset --hard v1.0
HEAD is now at 8984112 newfile a.txt
[root@oldboy ~/git_data]#ll
total 0
-rw-r--r-- 1 root root 0 May 29 09:09 a.txt

# 删除标签
[root@oldboy ~/git_data]#git tag -d v1.0
Deleted tag 'v1.0' (was 866c266)
[root@oldboy ~/git_data]#git tag -d v1.1
Deleted tag 'v1.1' (was 7157754)
[root@oldboy ~/git_data]#git tag 

3、gitlab

github #是公共平台 类似阿里云平台。开发经常使用、将自己开发的代码上传到github平台供其他人员使用。
码云 # 国内代码共享平台。
GitLab:
是一个用于仓库管理系统的开源项目。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。可通过Web界面进行访问公开的或者私人项目。它拥有与
Github类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。团队成员可以利用内置的简单聊
天程序(Wall)进行交流。它还提供一个代码片段收集功能可以轻松实现代码复用。
常用的网站:
官网:https://about.gitlab.com/
中文网站: https://gitlab.cn/
国内镜像:
https://mirrors.tuna.tsinghua.edu.cn/gitlab‐ce/yum/
1、ubt安装gitlab
安装环境:
1、 ubuntu22.04
2、 8G内存
3、 安装包:gitlab-ce_16.5.2-ce.0_amd64
4、 禁用防火墙,关闭selinux

# yum仓库更新安装和配置所需的依赖
sudo apt-get update
# 安装仓库依赖
sudo apt-get install -y curl openssh-server ca-certificates tzdata perl
# 通过curl到的bash脚本然后交给bash执行
curl -L get.gitlab.cn | bash

# 安装gitlab,时间大约40分钟
root@oldboy:~# EXTERNAL_URL="http://8.138.250.63" apt-get install -y gitlab-jh

root@ubuntu:~# gitlab-ctl status # 查看gitlab状态
root@ubuntu:~# gitlab-ctl stop   # 停止gitlab服务
root@ubuntu:~# gitlab-ctl start  # 启动gitlab服务

安装完成后访问8.138.250.63
默认用户: root
临时密码位置:cat /etc/gitlab/initial_root_password

2、创建新的项目

开发创建本地仓库git_data

1.通过vim编辑、2.通过git add .提交到暂存区、3.通过git commit -m "xxx"提交到仓库、4.将本地仓库的代码推送到远程仓库

创建项目的三种方式:
#1、已经存在的代码
1、gitlab创建game仓库
2、本地仓库中配置gitlab的game仓库为远程仓库
3、将本地仓库的游戏代码推送到远程gitlab的ganme仓库

#2、代码不存在,开发从头写
1、首先从gitlab创建test仓库
2、直接将test仓库clone到本地
3、本地可以看到test目录,并且远程仓库是gitlab的test仓库
4、直接在test目录写代码,提交到本地仓库,推送到远程仓库

#3、第三方代码
1、第三方的代码连接
2、将代码的连接导入到gitlab的仓库中即可
1、第一种方式

创建群组

1.添加远程仓库

[root@git ~/git_data]#git remote
# 添加一个远程仓库“origin”,链接地址为:git@10.0.0.201:oldboy/test.git
[root@git ~/git_data]#git remote add origin git@10.0.0.201:oldboy/test.git
[root@git ~/git_data]#git remote
origin
# 可以看到仓库的详细信息
[root@git ~/git_data]#git remote -v
origin	git@10.0.0.201:oldboy/test.git (fetch) # 拉取
origin	git@10.0.0.201:oldboy/test.git (push)  # 推送
# 删除远程仓库
[root@git ~/git_data]#git remote remove origin

2.做免密钥

#在推送之前需要先做免密钥,将kylin200的公钥放到ubuntu201 gitlab页面
[root@git ~]#ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in yes
Your public key has been saved in yes.pub
The key fingerprint is:
SHA256:CRfxHSl8YYkQVjO3EdAridsDKwCQ73FaWN6Ene/6fjQ root@git
The keys randomart image is:
+---[RSA 3072]----+
|.o   o .**=+B=   |
|. . o +. o+*=+   |
| . = o.....+o.   |
|  + = .o+.o .    |
| . = . .S= .     |
|  o   . + E      |
|       o . o     |
|      .   .      |
|       oo.       |
+----[SHA256]-----+

[root@git ~]#cat .ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPhKgLVj/iYrnEq4nVj4trux+ZWR+eJttAX6wlmRK4+9Ie9fWYyJ1NqXUu/eAK1ExbPlG4/O7
vwZIpF+wc8gq28trR6vwCp+CyDbU1JoTjjWjyanU8O7JqyGyCVJpfo/BSPPeVpqVCQXaEeaK+0pAnOIhvfgNmtez1Kgn7k4AkdzEkO4K92DlNE+
K8DKznEOyZkY9xDzzmCD2NEGRyJPom2s/A8PG4ADRcD2ieIo7QyhpYofFfqeG6d4Y9YuxAW6kZqqVUhSyml5TlZEmjG2RzXfQYJlgjtbdZ815qA
TCaXFSgkvq7qo1Vc6WLcPF0pQzOgDSEBU8Oi/8rMYiw54yLIZEnQ3VYnNCh6q9EsjpBpiusgCBRHqApVh6ZwOQ7OuCpw67/lxvLSzKQPeTME4Lo
ugIJqLnBkrgbqHvYEE/HtG9rp0R2fSVFVEh4CK0MP+GgtEXy70107DhePqsq5QvppFb+bMwZEpA30ZOCqhvUNmJkc11RGTJhu4eyfHAdMj0= 
root@git

3.将本地仓库的代码推送到远程gitlab的test仓库

# 将本地master分支推送到远程origin仓库
[root@git ~/git_data]#git push -u origin master
The authenticity of host 10.0.0.201 (10.0.0.201)' can't be established.
ECDSA key fingerprint is SHA256:ws3CQoYswByBQMVJKbuDH0vtlKBq2qSQXVAoWW0CulA.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.0.201' (ECDSA) to the list of known hosts.
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 206 bytes | 206.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To 10.0.0.201:oldboy/test.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

# 返回gitlab查看,可以看到代码已经同步到gitlab中

删除项目

设置-通用-往下拉找到高级-删除项目

2、第二种创建方式

# 将test1仓库clone到本地
[root@git ~]#git clone git@10.0.0.201:oldboy/test1.git
Cloning into 'test1'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.
[root@git ~]#ll
total 8
drwxr-xr-x 3 root root   31 May 29 11:30 git_data
drwxr-xr-x 3 root root   35 May 29 12:20 test1

[root@git ~/test1]#ll
total 8
-rw-r--r-- 1 root root 6103 May 29 12:20 README.md
# 克隆的自带远程仓库,并不需要配置
[root@git ~/test1]#git remote
origin
[root@git ~/test1]#git remote -v
origin	git@10.0.0.201:oldboy/test1.git (fetch)
origin	git@10.0.0.201:oldboy/test1.git (push)

# 创建代码文件推送到本地仓库
[root@git ~/test1]#touch 1.txt
[root@git ~/test1]#git add 1.txt
[root@git ~/test1]#git commit -m "1.txt"
[main 7b81125] 1.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 1.txt
[root@git ~/test1]#ll
total 8
-rw-r--r-- 1 root root    0 May 29 12:23 1.txt
-rw-r--r-- 1 root root 6103 May 29 12:20 README.md
# 查看git分支
[root@git ~/test1]#git branch
* main
# 将本地main分支推送到远程origin仓库
[root@git ~/test1]#git push -u origin main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 263 bytes | 263.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To 10.0.0.201:oldboy/test1.git
   2c3fcdf..7b81125  main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

#gitlab页面查看

# 将game仓库clone到本地
[root@git ~]#git clone git@10.0.0.201:oldboy/game.git
Cloning into 'game'...
warning: You appear to have cloned an empty repository.
[root@git ~]#ll
total 7728
drwxr-xr-x 3 root root      18 May 29 12:49  game

# 解压到gama目录
[root@git ~/game]#unzip '小霸王_FC怀旧游戏机-HTML源码_(1).zip' -d game
[root@git ~/game]#ll
total 48
-rw-r--r-- 1 root root 28032 May 24  2021 bgm.mp3
drwxr-xr-x 2 root root    23 May 24  2021 css
drwxr-xr-x 2 root root    23 May 24  2021 images
-rw-r--r-- 1 root root  8956 May 24  2021 index.html
drwxr-xr-x 2 root root   213 May 24  2021 js
drwxr-xr-x 2 root root  4096 May 24  2021 roms
-rw-r--r-- 1 root root   811 May 24  2021 shuoming.html

# 将代码推送到本地仓库,保证工作目录是干净的
[root@git ~/game]#git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    bgm.mp3
    css/
    images/
    index.html
    js/
    roms/
    shuoming.html

nothing added to commit but untracked files present (use "git add" to track)
[root@git ~/game]#git add .
[root@git ~/game]#git commit -m "xbw"

# 推送到远端
[root@git ~/game]#git push -u origin master
Enumerating objects: 98, done.
Counting objects: 100% (98/98), done.
Compressing objects: 100% (96/96), done.
Writing objects: 100% (98/98), 7.35 MiB | 5.75 MiB/s, done.
Total 98 (delta 3), reused 0 (delta 0), pack-reused 0
To 10.0.0.201:oldboy/game.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

# 查看gitlab页面

# 如何拉取刚上传的代码克隆到别的服务器
做免密钥,将kylin07的公钥放到ubuntu201 gitlab页面
[root@xxxx ~]#cat .ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwiPpshps3lfDel6wjszSRkNp6w29JYywvhHhXmu5vP8bOT61cJ4ZXXrwqtX0CvAuyzRVIfHP
fM8V/UTfadrct0fL6TC2PSxj/EvtfK0pQi3I+dCd1vAQFJCWI2ux/ooGnhCE0VQVn+Dolw3Pbf4MjifStE8TBxSMZ0CZrnak967J6ouh1rGDWF
ks0qwS2/qSKlcrAMVTVa9MPfsz6cJ+j7SOU+3Zgizv5BU0Yc9FXDozzDN42fpGwzVg8Q1JvrTej2grTB8K2Y46VBSuS4gR/4JtFIpiVbxqSR4u
L86NLTfxKJPGSK23X7ud33A0x1BQWzxX6tEQQYlEShKT+vRPMwJ8a0HKuvUfpP8la/dC0kk8nJl8UGhF7u1OmDi1YXsSvI84khrUR1lqwZCK
1rN5xrvdrYYQtNndFm69N7PvF3qgZ7XzDurWzGkjnkfSmsQNWSg9uFnrdANvH8H0//MN2UThZqeOVI0f/YOBvprACVgPE0UZum+Hw5soN8bGy
0F8= root@web01

# 拉取到本地
[root@xxxx /code/xy]#git clone git@10.0.0.201:oldboy/game.git
Cloning into game'...
The authenticity of host '10.0.0.201 (10.0.0.201)' can't be established.
ECDSA key fingerprint is SHA256:ws3CQoYswByBQMVJKbuDH0vtlKBq2qSQXVAoWW0CulA.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.0.201' (ECDSA) to the list of known hosts.
remote: Enumerating objects: 98, done.
remote: Counting objects: 100% (98/98), done.
remote: Compressing objects: 100% (96/96), done.
remote: Total 98 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (98/98), 7.53 MiB | 5.88 MiB/s, done.
Resolving deltas: 100% (3/3), done.

[root@xxxx /code/xy]#ll
total 48
-rw-r--r-- 1 root root 28032 May 29 13:06 bgm.mp3
drwxr-xr-x 2 root root    23 May 29 13:06 css
drwxr-xr-x 3 root root    18 May 29 13:07 game
drwxr-xr-x 2 root root    23 May 29 13:06 images
-rw-r--r-- 1 root root  8956 May 29 13:06 index.html
drwxr-xr-x 2 root root   213 May 29 13:06 js
drwxr-xr-x 2 root root  4096 May 29 13:06 roms
-rw-r--r-- 1 root root   811 May 29 13:06 shuoming.html

# 浏览器测试

3、创建普通用户

仪表盘-新建用户-填入用户名

创建完新用户dev,另开窗口无痕登录dev用户
切回管理员用户
        群组-进入oldboy小组-管理权限-邀请成员,选中dev用户,角色选择开发者

可以看到新添加的成员

# 开发所用的服务器做与dev用户的免密钥就可以成功拉取所看到的项目代码
[root@web01 ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:XRP4KKGBL7fNGhQoMW0t7n3FSwKet2Iy7uYyUHeQffc root@web01
The keys randomart image is:
+---[RSA 2048]----+
|  oo *     ..    |
|  ..O * o o  .   |
|   + = B + +o    |
|  . + O +.=.E.   |
| . o * =S*..     |
|.   + * = .      |
| . . + =         |
|  o o .          |
|   *o            |
+----[SHA256]-----+
[root@web01 ~]# cat .ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4+CZ9F5zi2HbPCS/npKfo4KOsk0ko3K356/h79fU78K9hnBJdmnFsrTgd6YsXrwL0Kr4r79S16+gUrq0hGCN/dDO6AL0jGIfunitoQ5TBxdzfy1PufvO/xQhe5AR6qI3iM+qUntSLFOsw7WuTJReK0/LxNxaDhoY2aPLZbN5W0SWZdUH2iKpzkkg43z6rEyDoBIFzGjCNFct6x6Dx++rlMaoOuOD/DHF6tiuQiC18M6LkXRObdmXpAwXWmtsOTkfPxtNy79XXnBTMc31WL3vS3zvPhopefwHi86BDf7ODntGf++n7X6WCJejghPhcbHqNURX3sMnDgYwYn2G2qkJ7 root@web01

# 添加免密钥

# 添加免密钥

# 拉取远程代码
[root@web01 code]# git clone git@8.138.120.235:oldboy/game.git
Cloning into 'game'...
remote: Enumerating objects: 98, done.
remote: Counting objects: 100% (98/98), done.
remote: Compressing objects: 100% (96/96), done.
remote: Total 98 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (98/98), 7.53 MiB | 691.00 KiB/s, done.
Resolving deltas: 100% (3/3), done.

什么时候用git clone?
本地没有代码的情况下

什么时候用git pull?
别的开发上传代码了或者在你上传之前不确定别人有没有上传,拉取一下试一下,更新下
4、模拟开发写完功能提交代码

1. 错误流程!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

# 直接在master进行修改
#1、创建开发者名称信息
[root@web01 game]# git config --global user.name "dev"
[root@web01 game]# git config --global user.email "dev@mail.com"
[root@web01 game]# git config --global color.ui true
[root@web01 game]# cat /root/.gitconfig 
[user]
    name = dev
    email = dev@mail.com
[color]
    ui = true

2、第90行的魂斗罗改成魂斗斗

['魂斗斗', 'roms/Contra1(U)30.nes'],

# 3、提交到本地仓库,git commit -am集成了git add .跟git commit -m ""。使用前提是已经提交到仓库了
[root@web01 game]# git commit -am "魂斗斗"
[master 8dd2d66] 魂斗斗
 1 file changed, 2 insertions(+), 2 deletions(-)

4、远程推送失败

[root@web01 game]# git push -u origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 290 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)   # 你无法推送至受保护的分支,开发者无权限
remote: GitLab: You are not allowed to push code to protected branches on this project.To git@8.138.120.235:oldboy/game.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@8.138.120.235:oldboy/game.git'

2.正确流程

1.创建新的testing分支

[root@web01 game]# git branch
* master
[root@web01 game]# git branch testing
[root@web01 game]# git branch
* master
  testing

2.把testing分支推送到项目中,此时第90行的魂斗罗已经改成了魂斗斗

[root@web01 game]# git push -u origin testing
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 290 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: 
remote: To create a merge request for testing, visit:
remote:   http://8.138.120.235/oldboy/game/-/merge_requests/new?merge_request%5Bsource_branch%5D=testing
remote: 
To git@8.138.120.235:oldboy/game.git
 * [new branch]      testing -> testing
Branch testing set up to track remote branch testing from origin.

# 普通用户页面可以看到,页面点击创建合并请求

回到管理员页面
    进入ganme项目可以看到“合并请求”
因为合并的时候删除了源分支,所以合并完成回到项目的时候,testing分支已经被删除了

# 测试合并后的代码是否是魂斗斗
#下载新的代码
[root@web01 code]# git clone git@8.138.120.235:oldboy/game.git
Cloning into 'game'...
remote: Enumerating objects: 102, done.
remote: Counting objects: 100% (102/102), done.
remote: Compressing objects: 100% (100/100), done.
remote: Total 102 (delta 5), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (102/102), 7.54 MiB | 686.00 KiB/s, done.
Resolving deltas: 100% (5/5), done.
[root@web01 code]# ll
total 4
drwxr-xr-x 7 root root 4096 May 29 20:46 game

# 访问,成功修改成魂斗斗

开发提交代码的第二种方式

 创建并切换到test分支 
[root@web01 game]# git checkout -b test
Switched to a new branch 'test'
[root@web01 game]# git branch
  master
* test

# 第90行修改为魂斗斗123
[root@web01 game]# vim index.html 
['魂斗斗123', 'roms/Contra1(U)30.nes'],

# 提交到本地仓库
[root@web01 game]# git add .
[root@web01 game]# git commit -m "魂斗斗123"
[test 0464fcf] 魂斗斗123
 1 file changed, 1 insertion(+), 1 deletion(-)
[root@web01 game]# git status
# On branch test
nothing to commit, working directory clean

# 注意! 切换到master分支进行提交
[root@web01 game]# git checkout master
Switched to branch 'master'
[root@web01 game]# git push -u origin test
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 289 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: 
remote: To create a merge request for test, visit:
remote:   http://8.138.120.235/oldboy/game/-/merge_requests/new?merge_request%5Bsource_branch%5D=test
remote: 
To git@8.138.120.235:oldboy/game.git
 * [new branch]      test -> test
Branch test set up to track remote branch test from origin.

# 返回dev页面会看到“创建合并请求”,点击并填写内容

4、Jenkins

官网 jenkins.io
Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。
1、安装jenkins
Kylin系统 10.0.0.202 1核2G内存
# 安装JDK运行环境
[root@jenkins:~]#yum -y install java
# 上传软件包并安装
[root@jenkins:~]#rpm -ivh jenkins-2.405-1.1.noarch.rpm
-------------------------------------------------------------------------------------------------------
#这里有个问题,centos默认安装完java环境后启动jenkins报错,原因是java版本太低
[root@jenkins ~]# systemctl start jenkins
Job for jenkins.service failed because the control process exited with error code. See "systemctl status jenkins.service" and "journalctl -xe" for details.

[root@jenkins ~]# java -version
openjdk version "1.8.0_412"
OpenJDK Runtime Environment (build 1.8.0_412-b08)
OpenJDK 64-Bit Server VM (build 25.412-b08, mixed mode)
# 查看本地jdk版本
[root@jenkins ~]# yum search java | grep openjdk
java-1.8.0-openjdk-src.x86_64 : OpenJDK 8 Source Bundle
java-11-openjdk.i686 : OpenJDK Runtime Environment 11
java-11-openjdk.x86_64 : OpenJDK 11 Runtime Environment
# 安装
[root@jenkins ~]# yum -y install java-11-openjdk

# 选择默认版本
[root@jenkins ~]# alternatives --config java

There are 3 programs which provide 'java'.

  Selection    Command
-----------------------------------------------
*+ 1           java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.412.b08-1.el7_9.x86_64/jre/bin/java)
   2           /usr/java/jdk1.8.0_181-amd64/jre/bin/java
   3           java-11-openjdk.x86_64 (/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64/bin/java)

Enter to keep the current selection[+], or type selection number: 3  #选择3
# 再次查看java版本
[root@jenkins ~]# java -version
openjdk version "11.0.23" 2024-04-16 LTS
OpenJDK Runtime Environment (Red_Hat-11.0.23.0.9-2.el7_9) (build 11.0.23+9-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-11.0.23.0.9-2.el7_9) (build 11.0.23+9-LTS, mixed mode, sharing)

# 已经成功启动
[root@jenkins ~]# systemctl status jenkins
● jenkins.service - Jenkins Continuous Integration Server
   Loaded: loaded (/usr/lib/systemd/system/jenkins.service; disabled; vendor preset: disabled)
   Active: activating (start) since Thu 2025-05-29 22:58:02 CST; 51s ago
 Main PID: 15831 (java)

-------------------------------------------------------------------------------------------------------

# 修改启动用户为root默认使用jenkins运行。
[root@jenkins:~]#grep root /usr/lib/systemd/system/jenkins.service
User=root
Group=root
# 重新加载配置文件
[root@jenkins:~]#systemctl daemon-reload
# 启动jenkins
[root@jenkins:~]#systemctl start jenkins
# 启动成功目录可以看到文件
[root@jenkins ~]# ll /var/lib/jenkins/
total 56
drwxr-xr-x 3 root root 4096 May 29 22:56 %C
-rw-r--r-- 1 root root 1658 May 29 23:02 config.xml
-rw-r--r-- 1 root root  156 May 29 23:01 hudson.model.UpdateCenter.xml
-rw-r--r-- 1 root root  171 May 29 22:56 jenkins.telemetry.Correlator.xml
drwxr-xr-x 2 root root 4096 May 29 22:56 jobs
-rw-r--r-- 1 root root  907 May 29 23:01 nodeMonitors.xml
drwxr-xr-x 2 root root 4096 May 29 22:56 nodes
drwxr-xr-x 2 root root 4096 May 29 22:56 plugins
-rw-r--r-- 1 root root  129 May 29 23:01 queue.xml.bak
-rw-r--r-- 1 root root   64 May 29 22:56 secret.key
-rw-r--r-- 1 root root    0 May 29 22:56 secret.key.not-so-secret
drwx------ 2 root root 4096 May 29 22:56 secrets
drwxr-xr-x 2 root root 4096 May 29 23:04 updates
drwxr-xr-x 2 root root 4096 May 29 22:56 userContent
drwxr-xr-x 3 root root 4096 May 29 22:56 users

#配置jenkins的插件
将jenkins_plu.tar.gz压缩包上传到/var/lib/jenkins/plugins解压
[root@jenkins:plugins]#tar xf jenkins_plu.tar.gz

# 重启jenkins生效
[root@jenkins:~]#systemctl restart jenkins

打开浏览器通过页面安装步骤
http://47.111.25.47:8080/

# 如果是云服务器访问失败,检查一下安全组规则是否放行了8080端口

页面安装

修改密码登录

创建测试任务

保存创建完成之后点立即构建

# 默认的工作目录,也就是jenkins的家/var/lib/jenkins/workspace
[root@jenkins workspace]# ll
total 4
drwxr-xr-x 2 root root 4096 May 30 09:20 测试任务
[root@jenkins workspace]# pwd
/var/lib/jenkins/workspace


配置-touch 1.log

# 可以看到新创建的文件
[root@jenkins 测试任务]# ll
total 0
-rw-r--r-- 1 root root 0 May 30 09:25 1.log
[root@jenkins 测试任务]# pwd
/var/lib/jenkins/workspace/测试任务

# 因为用的root用户启动,所以可以在别的地方创建文件
[root@jenkins ~]# ll
total 257260
-rw-r--r-- 1 root root         0 May 30 09:28 1.log
2、jenkins拉取gitlab代码到web服务器

创建game项目

这里有个问题,为什么8.138.250.63是gitlab服务器,而这里显示8.138.120.235呢,原因是之前使用阿里云 http://8.138.120.235/构建了
gitlab之后保存了镜像,然后服务器释放了,没多久又买了一台服务器http://8.138.250.63/用的是之前8.138.120.235服务器的镜像创建的实例,
现在问题是8.138.250.63服务器可以正常登录gitlab,但是之前创建的项目ip是8.138.120.235导致git没法用
# 实例迁移后遇到项目URL指向旧 IP 的问题,这是典型的配置残留问题。
步骤 1:修改 GitLab 外部 URL
登录新服务器:
ssh root@8.138.250.63
编辑 GitLab 主配置文件:
vim /etc/gitlab/gitlab.rb
# 修改为当前服务器IP
external_url 'http://8.138.250.63' 
# 重新加载,问题解决
root@gitlab:~# gitlab-ctl reconfigure
root@gitlab:~# gitlab-ctl restart

# 换成新ip又报错了,原因又两个,1是底层没有做免密钥,要把235这台的公钥放到gitlab中去。2是需要手动把项目拉取到本地一下,输入个“yes”

[root@jenkins tmp]# git clone git@8.138.250.63:oldboy/game.git
Cloning into 'game...
The authenticity of host '8.138.250.63 (8.138.250.63)' can't be established.
ECDSA key fingerprint is SHA256:W+umSUAQfaudsq8eZE4Qm7tN/RZJcoH+iptU5YgWmkI.
ECDSA key fingerprint is MD5:fd:b9:d1:ff:3d:10:5e:1f:5f:c7:49:52:0f:cc:df:a0.
Are you sure you want to continue connecting (yes/no)? yes   # 输入yes

保存后点击立即构建

# 目录下已经有了
[root@jenkins ganme]# pwd
/var/lib/jenkins/workspace/ganme
[root@jenkins ganme]# ll
total 60
-rw-r--r-- 1 root root 28032 May 30 10:29 bgm.mp3
drwxr-xr-x 2 root root  4096 May 30 10:29 css
drwxr-xr-x 2 root root  4096 May 30 10:29 images
-rw-r--r-- 1 root root  8956 May 30 10:29 index.html
drwxr-xr-x 2 root root  4096 May 30 10:29 js
drwxr-xr-x 2 root root  4096 May 30 10:29 roms
-rw-r--r-- 1 root root   811 May 30 10:29 shuoming.html

推送到web服务器

保存完-立即构建-失败了
# 原因是8.138.120.235与8.148.236.36之间没有做免密钥
[root@jenkins ganme]# ssh-copy-id 8.148.236.36

成功执行

# 配置nginx
[root@git /code/game]#cat /etc/nginx/conf.d/kod.conf 
server {
    listen 80 default;
    server_name _;

    location / {
    root /code/game;
    index index.html index.htm;
     }	 	
}
[root@git /code/game]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@git /code/game]#systemctl restart nginx 


3、jenkins配置webhook自动触发

# 1.更新看是否有新代码

[root@git ~/game]#git pull
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 8 (delta 0), reused 5 (delta 0), pack-reused 3 (from 1)
Unpacking objects: 100% (8/8), done.
From 8.138.250.63:oldboy/game
   099f5e1..d1a547a  master     -> origin/master
Updating 099f5e1..d1a547a
Fast-forward
 index.html | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

2.修改代码

['混蛋罗', 'roms/Contra1(U)30.nes'],

3.推送到本地仓库

[root@git ~/game]#git add .
[root@git ~/game]#git commit -m "混蛋"
[master 4683391] 混蛋
 1 file changed, 2 insertions(+), 2 deletions(-)

4.推送到远程gitlab的master分支,因为与管理员做了免密钥

[root@git ~/game]#git push -u origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 299 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@8.138.250.63:oldboy/game.git
   528394c..4683391  master -> master
Branch master set up to track remote branch master from origin.

5.jenkins直接执行立即构建,把从git本地仓库的项目推到远程gitlab服务器的代码下载到jenkins本地/var/lib/jenkins/workspace/ganme目录。再scp到47.111.25.47:/code/game/

刷新浏览器测试

配置自动触发

'

jenkins在自己的game项目中生成钥匙token给gitlab,gitlab在自己game项目中配置钥匙,当gitlab的master一变,gitlab拿着钥匙来
触发jenkins的game项目

允许网络请求

配置钩子

# 修改测试
['混蛋罗123', 'roms/Contra1(U)30.nes'],

# 提交到本地仓库
[root@git ~/game]#git add .
[root@git ~/game]#git commit -m "混蛋罗123"
[master 9854c6b] 混蛋罗123
 1 file changed, 1 insertion(+), 1 deletion(-)

# 推送到远程服务器master节点
[root@git ~/game]#git push -u origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 300 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@8.138.250.63:oldboy/game.git
   4683391..9854c6b  master -> master
Branch master set up to track remote branch master from origin.

# 浏览器测试

5、SonarQube代码扫描

jenkins将代码拉取到jenkins本地,先将代码推送到sonar服务器上代码扫描检测,检测漏洞 逻辑 坏味道。
1、安装

1.安装java

[root@SonarQube ~]# yum -y install java

2.安装mysql

[root@SonarQube ~]# wget dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
[root@SonarQube ~]# rpm -ivh mysql-community-release-el6-5.noarch.rpm 
[root@SonarQube ~]# yum -y install mariadb-server
启动mysql
[root@SonarQube ~]# service mysqld start
创建mysql密码
[root@SonarQube ~]# mysqladmin -uroot password lizhenya123
创建数据库
[root@SonarQube ~]# mysql -uroot -plizhenya123 -e "CREATE DATABASE sonar DEFAULT CHARACTER SET utf8;"
查看数据库
[root@SonarQube ~]# mysql -uroot -plizhenya123 -e "show databases;"
Warning: Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sonar              |
+--------------------+

3.安装sonarqube

上传软件包

解压

[root@SonarQube ~]# unzip sonarqube-7.0.zip -d /usr/local/
创建软连接
[root@SonarQube ~]# ln -s /usr/local/sonarqube-7.0/ /usr/local/sonarqube
修改连接数据库信息
[root@SonarQube ~]# cd /usr/local/sonarqube/conf/
[root@sonarqube:conf]#vim sonar.properties
修改配置文件的16 17和26行

 16 sonar.jdbc.username=root     
 17 sonar.jdbc.password=lizhenya123
 18 
 19 #----- Embedded Database (default)
 20 # H2 embedded database server listening port, defaults to 9092
 21 #sonar.embeddedDatabase.port=9092
 22 
 23 #----- MySQL 5.6 or greater
 24 # Only InnoDB storage engine is supported (not myISAM).
 25 # Only the bundled driver is supported. It can not be changed.
 26 sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true    &useConfigs=maxPerformance&useSSL=false

4.创建普通用户sonar

sonarqube服务必须由普通用户运行。
[root@SonarQube conf]# useradd sonar
[root@SonarQube conf]# chown -R sonar.sonar /usr/local/sonarqube-7.0/

5.使用sonar用户运行服务

[root@SonarQube conf]# su - sonar -c "/usr/local/sonarqube/bin/linux-x86-64/sonar.sh start"
Starting SonarQube...
Started SonarQube.

# sonar默认端口为9000
[root@SonarQube ~]# netstat -tnulp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1094/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1052/master         
tcp        0      0 127.0.0.1:32000         0.0.0.0:*               LISTEN      2060/java           
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      549/rpcbind         
tcp6       0      0 :::22                   :::*                    LISTEN      1094/sshd           
tcp6       0      0 ::1:25                  :::*                    LISTEN      1052/master         
tcp6       0      0 :::9000                 :::*                    LISTEN      2163/java           
tcp6       0      0 127.0.0.1:9001          :::*                    LISTEN      2082/java           
tcp6       0      0 :::3306                 :::*                    LISTEN      1377/mysqld         
tcp6       0      0 :::111                  :::*                    LISTEN      549/rpcbind         
udp        0      0 0.0.0.0:68              0.0.0.0:*                           800/dhclient  
# 这里有个错误,分配了2g显示Elasticsearch 已经成功启动,但随后被系统终止(exit code 137)。这通常是内存不足导致的内核OOMKiller 
# 介入的结果。调整内存大小为4g启动成功

6.安装插件

进入目录
[root@SonarQube ~]# cd /usr/local/sonarqube/extensions/
[root@SonarQube extensions]# cd plugins/
删除默认
[root@SonarQube plugins]# rm -rf *
上传插件
解压插件
[root@sonarqube:plugins]#tar xf sonar_plugins.tar.gz
[root@sonarqube:plugins]#mv plugins/* .

重启sonarqube服务
[root@SonarQube plugins]#  su - sonar -c "/usr/local/sonarqube/bin/linux-x86-64/sonar.sh restart"
Stopping SonarQube...
Waiting for SonarQube to exit...
Stopped SonarQube.
Starting SonarQube...
Started SonarQube.

# 再次登录,变成中文

2、sonar创建项目

sonar-scanner \
  -Dsonar.projectKey=html \
  -Dsonar.sources=. \
  -Dsonar.host.url=http://8.138.206.142:9000 \
  -Dsonar.login=3ab430110acf50b8df9caa51a11d1da7ac822865

# 第二遍搭的
sonar-scanner \
  -Dsonar.projectKey=html \
  -Dsonar.sources=. \
  -Dsonar.host.url=http://47.111.25.47:9000 \
  -Dsonar.login=a6e032b1a51e9842c44ed9e0f535728d4babb469

3、客户端执行代码扫描上传到sonar服务器
需要在jenkins安装sonar客户端,因为需要把代码拉取到jenkins,在jenkins调取sonar客户端推送到sonar服务器进行代码质量检测

安装客户端:

# 上传包解压

[root@jenkins ~]# unzip sonar-scanner-cli-4.2.0.1873-linux.zip -d /usr/local
[root@jenkins ~]# cd /usr/local/
# 创建软连接
[root@jenkins local]# ln -s sonar-scanner-4.2.0.1873-linux/ sonar
[root@jenkins bin]# pwd
/usr/local/sonar/bin
[root@jenkins bin]# ll
total 8
-rwxr-xr-x 1 root root 1771 Oct  1  2019 sonar-scanner
-rwxr-xr-x 1 root root  610 Oct  1  2019 sonar-scanner-debug

# 将客户端写入PATH命令
[root@jenkins ~]# tail -1 /etc/profile
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/usr/local/sonar/bin"
[root@jenkins local]# source /etc/profile
[root@jenkins local]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/usr/local/sonar/bin

# 进入到代码目录
[root@jenkins ~]# cd /var/lib/jenkins/workspace/ganme/
[root@jenkins ganme]# ll
total 60
-rw-r--r-- 1 root root 28032 May 30 10:29 bgm.mp3
drwxr-xr-x 2 root root  4096 May 30 10:29 css
drwxr-xr-x 2 root root  4096 May 30 10:29 images
-rw-r--r-- 1 root root  8960 May 30 11:53 index.html
drwxr-xr-x 2 root root  4096 May 30 10:29 js
drwxr-xr-x 2 root root  4096 May 30 10:29 roms
-rw-r--r-- 1 root root   811 May 30 10:29 shuoming.html

# 执行代码扫描
[root@jenkins ganme]# sonar-scanner \
>   -Dsonar.projectKey=html \
>   -Dsonar.sources=. \
>   -Dsonar.host.url=http://8.138.206.142:9000 \
>   -Dsonar.login=3ab430110acf50b8df9caa51a11d1da7ac822865
INFO: Scanner configuration file: /usr/local/sonar-scanner-4.2.0.1873-linux/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarQube Scanner 4.2.0.1873
INFO: Java 11.0.3 AdoptOpenJDK (64-bit)
INFO: Linux 3.10.0-1160.119.1.el7.x86_64 amd64
INFO: User cache: /root/.sonar/cache
INFO: SonarQube server 7.0.0
INFO: Default locale: "en_US", source code encoding: "UTF-8" (analysis is platform dependent)
。。。
INFO: More about the report processing at http://8.138.206.142:9000/api/ce/task?id=AZcf6pW7utqRfyAaOpgN
INFO: Task total time: 16.693 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 1:56.651s
INFO: Final Memory: 14M/150M
INFO: ------------------------------------------

返回浏览器查看

4、sonar集成到jenkins上自动推送

服务器端配置好了

snoar.projectName=${JOB_NAME}
sonar.projectKey=html
sonar.sources=.
sonar.projectName=${JOB_NAME} # 项目在sonarqube上的显示名称
sonar.projectKey=html # 项目的唯一表示,不能重复
sonar.sources=. # 扫描那个项目的源码

# 运行测试
# 这里有个问题,sonar集成到jenkins上自动推送,我这只改了sonar内存到4g,放到jenkins里面也得需要至少2g的内存,所以jenkins也得4g

跑一遍流程

1.修改代码

[root@git ~/game]#vim index.html 
['魂斗罗', 'roms/Contra1(U)30.nes'],

2.提交到仓库

[root@git ~/game]#git commit -am "魂斗罗"
[master 87c0642] 魂斗罗
 1 file changed, 1 insertion(+), 1 deletion(-)

3.推送到远程

[root@git ~/game]#git push -u origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 304 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@8.138.250.63:oldboy/game.git
   9854c6b..87c0642  master -> master
Branch master set up to track remote branch master from origin

已经自动推送到web服务器

6、token丢失或者创建新项目

5、代码发布测试流程

6、配置企业微信

1.由于jenkins没有官网的插件来完成此功能,所以我们只能用网络上一些开源的插件(线下班不需要以下步骤,已集合在plugins)
github下载代码
https://github.com/daniel-beck/changelogenvironment-plugin
解压到某个目录-》进入目录执行以下操作
cd 到 changelog-environment-plugin-master下,执行mvn verify
时间较长,会在changelog-environment-pluginmaster/target/下有个changelogenvironment.hpi文件,上传到jenkins即可使用

2.配置jenkins
jenkins进入到项目中->构建环境多了Add Changelog Information to Environment->
点击选择 Entry Format中添加 %3$s(at %4$s via %1$s),参数分别为ChangeLog内容,时间,提交人。
Date Format中添加 yyyy‐MM‐dd HH:mm:ss 就是时间格式。

1.注册企业微信 https://mp.weixin.qq.com/
2.上传py脚本
[root@jenkins:~]#ll 
total 4
-rw-r--r-- 1 root root 2008 Sep 28 14:59
jenkins_notify.py
3.修改信息
[root@jenkins ~]# vim jenkins_notify.py 
 34         "touser" : "ZhangWeiXiang",   
 63     Corpid = "wwc2749ba833b4e897"
 64     Secret = "XUc23DnuGn-YcAzpa4T9_7yQc43IzgZL96XqtM5-9Ao"

4.# 命令行测试,kylin可以
[root@jenkins:~]#yum -y install python2
[root@jenkins:~]#yum -y install python2-pip

可以正常访问

# 因为是centons,可能版本不兼容,需要python3以上的版本
[root@sonar ~]# pip2.7 install requests
Collecting requests
  Downloading http://mirrors.cloud.aliyuncs.com/pypi/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz (131kB)
    100% |████████████████████████████████| 133kB 16.8MB/s 
    Complete output from command python setup.py egg_info:
    
    ==========================
    Unsupported Python version
    ==========================
    This version of Requests requires at least Python 3.8, but
    you're trying to install it on Python 2.7. To resolve this,
    consider upgrading to a supported Python version.
    
    If you cant upgrade your Python version, you'll need to
    pin to an older version of Requests (<2.32.0).
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-sJ1R7V/requests/
You are using pip version 8.1.2, however version 25.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

[root@sonar ~]# python --version
Python 2.7.5
# centos执行
[root@jenkins ~]# pip3 install requests
[root@jenkins scripts]# python3 jen.py test /etc/hosts game

# 优化py代码


[root@sonar opt]# cat jen.py 
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import requests
import sys
import json
import urllib3
urllib3.disable_warnings()

# 移除 Python 2 特有的代码
# reload(sys)
# sys.setdefaultencoding('utf-8')

def GetToken(Corpid, Secret):
    Url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
    Data = {
        "corpid": Corpid,
        "corpsecret": Secret
    }
    r = requests.get(url=Url, params=Data, verify=False)
    Token = r.json()['access_token']
    return Token

def SendMessage(Token, Subject, Content, ProName):
    Url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s" % Token
    data = {
        "touser": "ZhangWeiXiang",
        "msgtype": "text",
        "agentid": 1000002,   # 企业微信AgentId
        "text": {
            "content": "[项目名称] : " + ProName + '\n' + 
                       "[项目地址] : " + Subject + '\n' + 
                       Content + '\n'
        },
        "safe": 0
    }
    r = requests.post(url=Url, data=json.dumps(data), verify=False)
    return r.text

def action_from_file(filename):
    try:
        str1 = '[变更日志] : '
        with open(filename, 'r', encoding='utf-8') as f:
            for i in f.readlines():
                str1 += i
        # 修复缩进问题,使用空格代替制表符
        if len(str1) == 17:
            str1 += " 无变更"
        return str1
    except Exception as e:
        # 使用 Python 3 的 print 函数
        print(f'[ERROR] {e}')
        str1 += str(e)
        return str1

if __name__ == '__main__':
    Corpid = "wwc2749ba833b4e897"   
    Secret = "XUc23DnuGn-YcAzpa4T9_7yQc43IzgZL96XqtM5-9Ao"

    Subject = sys.argv[1]
    Content = action_from_file(sys.argv[2])
    ProName = sys.argv[3]

    Token = GetToken(Corpid, Secret)
    Status = SendMessage(Token, Subject, Content, ProName)
    print(Status)


# 测试,成功

1、企业微信集成到jenkins

输入打印的信息内容

# 存放上面内容
echo "==========Start Notify=============="
echo ${SCM_CHANGELOG} > /tmp/${JOB_NAME}_change.log
python3 /server/scripts/jen.py ${BUILD_URL} /tmp/${JOB_NAME}_change.log ${JOB_NAME}
rm -fv /tmp/${JOB_NAME}_change.log


# 脚本移动到server/scripts/
[root@sonar opt]# mkdir -p /server/scripts/
[root@sonar opt]# mv jen.py /server/scripts/
[root@sonar opt]# ll /server/scripts/
total 4
-rw-r--r-- 1 root root 1840 Jun  2 15:54 jen.py


2、测试流程
# 修改代码提交到本地仓库
[root@git ~/game]#vim index.html 
[root@git ~/game]#git add .
[root@git ~/game]#git commit -m "魂斗罗v1.1"
[master 70912ac] 魂斗罗v1.1
 1 file changed, 1 insertion(+), 1 deletion(-)
# 推送到gitlab远程,剩余自动执行
[root@git ~/game]#git push -u origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 302 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@8.138.250.63:oldboy/game.git
   9b2583b..70912ac  master -> master
Branch master set up to track remote branch master from origin.

# 项目代码已经改变

# jenkins已经正常执行

# 已经正常推送

7、代码线上业务发布流程

1、Jenkins参数构建配置

项目配置

# 创建标签
[root@git ~/game]#git tag -a v1.0 -m "v1.0"
[root@git ~/game]#git tag
v1.0
[root@git ~/game]#git show v1.0
tag v1.0
Tagger: lizhenya <lizhenya@mail.com>
Date:   Fri May 30 17:55:09 2025 +0800

v1.0

commit 87c06422dc2b78f94addb49d543e44740606e3a4
Author: lizhenya <lizhenya@mail.com>
Date:   Fri May 30 15:38:28 2025 +0800

    魂斗罗

diff --git a/index.html b/index.html
index 46cd32f..267e4a8 100644
--- a/index.html
+++ b/index.html
@@ -87,7 +87,7 @@
         nes = new JSNES({
             'ui': $('#emulator').JSNESUI({
                 "经典": [
-                    ['混蛋罗123', 'roms/Contra1(U)30.nes'],
+                    ['魂斗罗', 'roms/Contra1(U)30.nes'],
                     ['超级玛丽', 'roms/(W) Super Mario Bros. [!].nes'],
                     ['坦克', 'roms/(Ch) Missile Tank.nes'],
                     ['双截龙', 'roms/Double Dragon1.nes'],
# 推送到远程
[root@git ~/game]# git push -u origin v1.0
Counting objects: 1, done.
Writing objects: 100% (1/1), 151 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@8.138.250.63:oldboy/game.git
 * [new tag]         v1.0 -> v1.0

Jenkins获取gitlab标签

# 测试
# 修改代码内容
['魂斗罗1.1', 'roms/Contra1(U)30.nes'],

# 提交到本地仓库
[root@git ~/game]#git commit -am "v1.1"
[master bcf41c1] v1.1
 1 file changed, 1 insertion(+), 1 deletion(-)
[root@git ~/game]#git tag -a v1.1 -m "v1.1"

# 推送到远程
[root@git ~/game]#git push -u origin v1.1
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 401 bytes | 0 bytes/s, done.
Total 4 (delta 2), reused 0 (delta 0)
To git@8.138.250.63:oldboy/game.git
 * [new tag]         v1.1 -> v1.1

# 可以看到新创建的v1.1

2、实现秒级回滚

# 脚本内容
[root@jenkins ~]# cat deploy.sh 
#!/bin/bash
code_tar(){
tar zcvf /opt/web.tar.gz ./*
}
code_cp(){
scp /opt/web.tar.gz 47.111.25.47:/code/
}
code_un(){
ssh 47.111.25.47 "mkdir -p /code/web_code_$git_version" ssh 47.111.25.47 "cd /code;tar xf web.tar.gz -C web_code_$git_version && rm -rf web.tar.gz" }
code_ln(){
ssh 47.111.25.47 "rm -rf /code/game && ln -s /code/web_code_$git_version /code/game"
}
main(){
        code_tar
        code_cp
        code_un
        code_ln
}
if [ $deploy_env = "deploy" ];then
        main
elif [ $deploy_env = "rollback" ];then
        code_ln
fi

# 检测脚本语法
[root@jenkins ~]# bash -n /root/deploy.sh

执行v1.0版本

# 执行完毕后根据tag标签创建了目录并且自动创建了软连接
[root@web02 code]# ll
total 4
lrwxrwxrwx 1 root root   19 May 30 19:02 game -> /code/web_code_v1.0
drwxr-xr-x 6 root root 4096 May 30 19:02 web_code_v1.0

#浏览器可以正常访问

构建v1.1版本

# 执行完毕后把软连接指向了新发布的v1.1目录
[root@web02 code]# ll
total 8
lrwxrwxrwx 1 root root   19 May 30 19:14 game -> /code/web_code_v1.1
drwxr-xr-x 6 root root 4096 May 30 19:02 web_code_v1.0
drwxr-xr-x 6 root root 4096 May 30 19:14 web_code_v1.1

避免重复构建
当重复执行构建后会生成多个相同版本的文件,利用jenkins变量值解决重复性构建问题
jenkins变量
1. GIT_COMMIT 当前版本提交产生的哈希唯一值
2. GIT_PREVIOUS_SUCCESSFUL_COMMIT 已经提交过的版本的哈希唯一值
使用以上两个值做比较,如果已提交则退出,如果没有提交过则继续执行构建,更改脚本做判断
[root@jenkins ~]# cat deploy.sh 
#!/bin/bash
code_tar(){
tar zcvf /opt/web.tar.gz ./*
}

code_cp(){
scp /opt/web.tar.gz 47.111.25.47:/code/
}

code_un(){
ssh 47.111.25.47 "mkdir -p /code/web_code_$git_version" 
ssh 47.111.25.47 "cd /code;tar xf web.tar.gz -C web_code_$git_version && rm -rf web.tar.gz" 
}
code_ln(){
ssh 47.111.25.47 "rm -rf /code/game && ln -s /code/web_code_$git_version /code/game"
}

main(){
        code_tar
        code_cp
        code_un
        code_ln
}
if [ $deploy_env = "deploy" ];then
    if [ "$GIT_COMMIT" == "$GIT_PREVIOUS_SUCCESSFUL_COMMIT" ];then 
        echo "构建失败该 $git_version 版本号已部署"
        exit
    else
                main
    fi
elif [ $deploy_env = "rollback" ];then
        code_ln
fi

8、java项目发布流程

Maven是一个项目管理和综合工具。Maven提供给开发人员构建一个完整的生命周期框架。
开发团队可以自动完成该项目的基础设施建设,Maven使用标准的目录结构和默认构建生命周期。
Apache的开源项目主要服务于JAVA平台的构建、依赖管理、项目管理。
Project Object Model,项目对象模型。通过xml格式保存的pom.xml文件。该文件用于管理:源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目
授权、项目的url、项目的依赖关系等等。该文件是由开发维护,我们运维人员可以不用去关心。


2、Maven安装

1、下载Maven 3安装包

官网:http://maven.apache.org/download.cgi
清华镜像:https://mirrors.tuna.tsinghua.edu.cn/apache/maven/

2、上传java代码

3、安装Maven

[root@jenkins ~]# tar -xf apache-maven-3.3.9-bin.tar.gz -C /usr/local
[root@jenkins ~]# cd /usr/local
[root@jenkins local]# ln -s apache-maven-3.3.9/ maven

4、加入到PATH变量

[root@jenkins maven]# cd bin/
[root@jenkins bin]# pwd
/usr/local/maven/bin
[root@jenkins bin]# PATH="$PATH:/usr/local/maven/bin"
# 添加到/etc/profile
[root@jenkins bin]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/usr/local/sonar/bin:/root/bin:/usr/local/maven/bin

5、打包项目

[root@jenkins:~]#cd hello-world-war/
[root@jenkins:hello-world-war]#mvn package
...
[INFO] Packaging webapp
[INFO] Assembling webapp [hello-world-war] in [/root/hello-world-war/target/hello-world-war-1.0.0]
[INFO] Processing war project
[INFO] Copying webapp resources [/root/hello-world-war/src/main/webapp]
[INFO] Building war: /root/hello-world-war/target/hello-world-war-1.0.0.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 04:03 min
[INFO] Finished at: 2025-05-31T08:07:51+08:00
[INFO] Final Memory: 15M/154M
[INFO] ------------------------------------------------------------------------

[root@jenkins hello-world-war]# ll
total 20
drwxr-xr-x 2 root root 4096 May 23  2014 dist
-rw-r--r-- 1 root root  931 May 14  2024 pom.xml
-rw-r--r-- 1 root root  213 May 23  2014 README.md
drwxr-xr-x 3 root root 4096 May 23  2014 src
drwxr-xr-x 4 root root 4096 May 31 08:07 target   # 多出一个target目录
[root@jenkins hello-world-war]# ll target/
total 12
drwxr-xr-x 4 root root 4096 May 31 08:07 hello-world-war-1.0.0
-rw-r--r-- 1 root root 1934 May 31 08:07 hello-world-war-1.0.0.war   # 这个就是我们想要的
drwxr-xr-x 2 root root 4096 May 31 08:07 maven-archiv

6.web02部署tomcat

[root@web02 ~]# yum -y install java
[root@web02 ~]# wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.105/bin/apache-tomcat-9.0.105.tar.gz
[root@web02 ~]# tar xf apache-tomcat-9.0.105.tar.gz 
[root@web02 ~]# ll
total 12700
drwxr-xr-x 9 root root     4096 May 31 08:20 apache-tomcat-9.0.105
-rw-r--r-- 1 root root 13000541 May 31 08:18 apache-tomcat-9.0.105.tar.gz
[root@web02 ~]# mv apache-tomcat-9.0.105 /usr/local/tomcat
[root@web02 ~]# /usr/local/tomcat/bin/startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
Tomcat started.

7.web清空之前的

[root@web02 tomcat]# cd webapps//ROOT/
[root@web02 ROOT]# ll
total 168
-rw-r----- 1 root root 27235 May  8 02:36 asf-logo-wide.svg
-rw-r----- 1 root root   713 May  8 02:36 bg-button.png
-rw-r----- 1 root root  1918 May  8 02:36 bg-middle.png
-rw-r----- 1 root root  1401 May  8 02:36 bg-nav.png
-rw-r----- 1 root root  3103 May  8 02:36 bg-upper.png
-rw-r----- 1 root root 21630 May  8 02:36 favicon.ico
-rw-r----- 1 root root 12234 May  8 02:36 index.jsp
-rw-r----- 1 root root  6902 May  8 02:36 RELEASE-NOTES.txt
-rw-r----- 1 root root  5584 May  8 02:36 tomcat.css
-rw-r----- 1 root root 67795 May  8 02:36 tomcat.svg
drwxr-x--- 2 root root  4096 May 31 08:20 WEB-INF
[root@web02 ROOT]# pwd
/usr/local/tomcat/webapps/ROOT
[root@web02 ROOT]# rm -rf *

8.拷贝war包到web

[root@jenkins hello-world-war]# scp target/hello-world-war-1.0.0.war 47.111.25.47:/usr/local/tomcat/webapps/ROOT
hello-world-war-1.0.0.war 

9.回web解压

[root@web02 ROOT]# unzip hello-world-war-1.0.0.war 
Archive:  hello-world-war-1.0.0.war
  inflating: META-INF/MANIFEST.MF    
   creating: WEB-INF/
   creating: WEB-INF/classes/
  inflating: WEB-INF/web.xml         
  inflating: index.jsp               
  inflating: META-INF/maven/com.efsavage/hello-world-war/pom.xml  
  inflating: META-INF/maven/com.efsavage/hello-world-war/pom.properties  
[root@web02 ROOT]# ll
total 16
-rw-r--r-- 1 root root 1934 May 31 08:23 hello-world-war-1.0.0.war
-rw-r--r-- 1 root root  210 Oct 15  2019 index.jsp
drwxr-xr-x 3 root root 4096 May 31 08:24 META-INF
drwxr-xr-x 3 root root 4096 May 31 08:07 WEB-INF
重启生效
[root@web02 ROOT]# /usr/local/tomcat/bin/shutdown.sh 
[root@web02 ROOT]# /usr/local/tomcat/bin/startup.sh 

# 访问测试

3、集成到Jenkins
1. 清理生成的target包
[root@jenkins hello-world-war]# mvn clean

2. gitlab新建项目组

3. 上传到远程

3. 上传到远程
[root@jenkins hello-world-war]# git status
# On branch master
# Your branch is ahead of 'origin/master' by 3 commits.
#   (use "git push" to publish your local commits)
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   pom.xml
#	modified:   src/main/webapp/index.jsp
#
no changes added to commit (use "git add" and/or "git commit -a")
# 上传到本地仓库
[root@jenkins hello-world-war]# git add .
[root@jenkins hello-world-war]# git commit -m "xx"
[master 86168c9] xx
 2 files changed, 3 insertions(+), 3 deletions(-)
# 删除之前的
[root@jenkins hello-world-war]# git remote
origin
[root@jenkins hello-world-war]# git remote remove origin
[root@jenkins hello-world-war]# git remote
# 设置git@8.138.250.63:oldboy/java.git为远程仓库
[root@jenkins hello-world-war]# git remote add origin git@8.138.250.63:oldboy/java.git
[root@jenkins hello-world-war]# git remote -v
origin	git@8.138.250.63:oldboy/java.git (fetch)
origin	git@8.138.250.63:oldboy/java.git (push)
# 推送到远程,报错了,原因是这台服务器与gitlab的普通用户做了免密钥导致权限不够,解决办法,删除普通用的的密钥,与管理员做免密钥
[root@jenkins hello-world-war]# git push -u origin master
Counting objects: 44, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (29/29), done.
Writing objects: 100% (44/44), 4.89 KiB | 0 bytes/s, done.
Total 44 (delta 11), reused 0 (delta 0)
remote: GitLab: 
remote: A default branch (e.g. main) does not yet exist for oldboy/java
remote: Ask a project Owner or Maintainer to create a default branch:
remote: 
remote:   http://8.138.250.63/oldboy/java/-/project_members
remote: 
To git@8.138.250.63:oldboy/java.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@8.138.250.63:oldboy/java.git'

删除普通用户免密钥,新增管理员密钥,浏览器测试

# 进入Jenkins工作目录,已经成功编译了
[root@jenkins hello-world-war]# cd /var/lib/jenkins/workspace/
[root@jenkins workspace]# ll
total 16
drwxr-xr-x 7 root root 4096 May 30 19:19 deploy
drwxr-xr-x 8 root root 4096 May 30 15:38 ganme
drwxr-xr-x 6 root root 4096 May 31 09:28 java
drwxr-xr-x 2 root root 4096 May 30 09:25 测试任务
[root@jenkins workspace]# ll java/
total 20
drwxr-xr-x 2 root root 4096 May 31 09:26 dist
-rw-r--r-- 1 root root  931 May 31 09:26 pom.xml
-rw-r--r-- 1 root root  213 May 31 09:26 README.md
drwxr-xr-x 3 root root 4096 May 31 09:26 src
drwxr-xr-x 4 root root 4096 May 31 09:28 target  # gitlab是没有这个目录的

# 查看,已经创建软连接
[root@web02 webapps]# ll
total 28
drwxr-x--- 16 root root 4096 May 31 08:20 docs
drwxr-x---  7 root root 4096 May 31 08:20 examples
drwxr-x---  4 root root 4096 May 31 09:52 hello-world-war-1.0.0
-rw-r--r--  1 root root 1933 May 31 09:52 hello-world-war-1.0.0.war
drwxr-x---  6 root root 4096 May 31 08:20 host-manager
drwxr-xr-x  4 root root 4096 May 31 09:52 java_5
drwxr-x---  6 root root 4096 May 31 08:20 manager
lrwxrwxrwx  1 root root    6 May 31 09:52 ROOT -> java_5

# 修改代码测试
[root@jenkins hello-world-war]# vim src/main/webapp/index.jsp 
v1.0改为v1.1
# 上传到仓库
[root@jenkins hello-world-war]# git commit -am "v1.1"
[master c0eb105] v1.1
 1 file changed, 1 insertion(+), 1 deletion(-)
# 上传到本地仓库
[root@jenkins hello-world-war]# git push -u origin master
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 432 bytes | 0 bytes/s, done.
Total 6 (delta 2), reused 0 (delta 0)
To git@8.138.250.63:oldboy/java.git
   86168c9..c0eb105  master -> master
Branch master set up to track remote branch master from origin.

# 返回Jenkins点击立即构建,没问题

4、修改默认的中央仓库
# 编译会去中央仓库下载依赖,下载速度特别慢,因为仓库是国外的
[root@jenkins hello-world-war]# mvn package

# 中央仓库缓存位置
[root@jenkins ~]# cd .m2/
[root@jenkins .m2]# ll
total 4
drwxr-xr-x 11 root root 4096 May 31 08:07 repository
[root@jenkins .m2]# ll repository/
total 36
drwxr-xr-x 3 root root 4096 May 31 08:05 backport-util-concurrent
drwxr-xr-x 3 root root 4096 May 31 08:04 classworlds
drwxr-xr-x 3 root root 4096 May 31 08:05 com
drwxr-xr-x 3 root root 4096 May 31 08:04 commons-cli
drwxr-xr-x 3 root root 4096 May 31 08:07 commons-io
drwxr-xr-x 3 root root 4096 May 31 08:05 commons-logging
drwxr-xr-x 3 root root 4096 May 31 08:04 junit
drwxr-xr-x 3 root root 4096 May 31 08:05 log4j
drwxr-xr-x 8 root root 4096 May 31 08:07 org

# 进入settings.xml文件修改
[root@jenkins conf]# pwd
/usr/local/maven/conf
[root@jenkins conf]# vim settings.xml 
159     <mirror>
160           <id>nexus-aliyun</id>

161           <mirrorOf>*</mirrorOf>

162           <name>Nexus aliyun</name>

163           <url>http://maven.aliyun.com/nexus/content/groups/public</url> 
164     </mirror>

165   </mirrors>  # 这行不用粘贴

# 回到hellowork目录mvn 测试
[root@jenkins hello-world-war]# cd hello-world-war/
[root@jenkins hello-world-war]# mvn clean
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Hello World Web Application Repository 1.0.0
[INFO] ------------------------------------------------------------------------
Downloading: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom

注意:如果公司部分java代码 不需要配置nexus私服,只需要将maven配置文件仓库指向阿里云仓库
如果公司是重java项目,则需要搭建私有的仓库nexus
5、配置nexus私服

类似代理的作用,编译去找nexus私服,nexus去找阿里云的仓库,找到自己缓存一份,给java一份
部署私服 xenus 下载https://www.sonatype.com/download‐oss‐sonatype
配置仓库两个选项
1、项目下的pom.xml配置、只生效当前的项目
2、在maven配置全局所有项目生效

# 上传JDK
[root@nexus:~]#rpm -ivh jdk-8u181-linuxx64.rpm
# 上传nexus安装包
-rw-r--r-- 1 root root 122904706 Sep 27 17:19 nexus-3.13.0-01-unix.tar.gz
#解压代码
[root@nexus:~]#tar xf nexus-3.13.0-01-unix.tar.gz
#移动到/usr/local/nexus
[root@nexus:~]#mv nexus-3.13.0-01 /usr/local/nexus
# 启动nexus
[root@nexus:~]#/usr/local/nexus/bin/nexus start
# 查看服务是否启动
[root@web02 ~]# netstat -tnulp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name          
tcp        0      0 0.0.0.0:8081            0.0.0.0:*               LISTEN      1366/java  
# 浏览器访问
47.111.25.47:8081 admin admin123

浏览器配置nexus

# 修改maven配置文件
[root@jenkins conf]# cd /usr/local/maven/conf
[root@jenkins conf]# vim settings.xml

156   <mirrors>
157   <mirror>
158   <id>nexus</id>

159   <mirrorOf>*</mirrorOf>

160   <url>http://47.111.25.47:8081/repository/maven-public/</url>      # 修改为对应的ip
161 </mirror>

。。。
262 <profile>
263   <id>nexus</id>

264   <repositories>
265     <repository>
266       <id>central</id>

267       <url>http://47.111.25.47:8081/repository/maven-public/</url>   # 修改为对应的ip
268       <releases><enabled>true</enabled></releases>

269       <snapshots><enabled>true</enabled></snapshots>

270     </repository>

271   </repositories>

272  <pluginRepositories>
273     <pluginRepository>
274       <id>central</id>

275       <url>http://47.111.25.47:8081/repository/maven-public/</url>  # 修改为对应的ip
276       <releases><enabled>true</enabled></releases>

277       <snapshots><enabled>true</enabled></snapshots>

278     </pluginRepository>

279   </pluginRepositories>

280 </profile>

281   </profiles>

# 测试,已经去找刚才配置的47.111.25.47地址了
[root@jenkins hello-world-war]# mvn clean
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Hello World Web Application Repository 1.0.0
[INFO] ------------------------------------------------------------------------
Downloading: http://47.111.25.47:8081/repository/maven-public/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom
Downloaded: http://47.111.25.47:8081/repository/maven-public/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom (0 B at 0.0 KB/sec)
Downloading: http://47.111.25.47:8

9、Jenkins Pipeline项目

1.CI/CD持续集成/持续部署
持续集成(Continuous integration)是一种软件开发实践,即团队开发成员经常集成它们的工作,通过每个成员每天至少集成一次,也就意味着每天
可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
比如(你家装修厨房,其中一项是铺地砖,边角地砖要切割大小。如果一次全切割完再铺上去,发现尺寸有误的话浪费和返工时间就大了,不如切一块铺
一块。这就是持续集成。)

持续部署(continuous deployment)是通过自动化的构建、测试和部署循环来快速交付高质量的产品。某种程度上代表了一个开发团队工程化的程度,
毕竟快速运转的互联网公司人力成本会高于机器,投资机器优化开发流程化相对也提高了人的效率。
比如(装修厨房有很多部分,每个部分都有检测手段,如地砖铺完了要测试漏水与否,线路铺完了要通电测试电路通顺,水管装好了也要测试冷水热水。
如果全部装完了再测,出现问题可能会互相影响,比如电路不行可能要把地砖给挖开……。那么每完成一部分就测试,这是持续部署。)

持续交付 Continuous Delivery:频繁地将软件的新版本,交付给质量团队或者用户,以供评审尽早发现生产环境中存在的问题;如果评审通过,代码
就进入生产阶段比如(全部装修完了,你去验收,发现地砖颜色不合意,水池太小,灶台位置不对,返工吗?所以不如没完成一部分,你就去用一下试用验
收,这就是持续交付。)

敏捷思想中提出的这三个观点,还强调一件事:通过技术手段自动化这三个工作。加快交付速度。
2.pipeline介绍
1.什么是pipeline
Jenkins 2.0的精髓是Pipeline as Code,是帮助Jenkins实现CI到CD转变的重要角色。什么是Pipeline,简单来说,就是一套运行于Jenkins
上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程。Pipeline的实现方式是一套Groovy DSL,
任何发布流程都可以表述为一段Groovy脚本,并且Jenkins支持从代码库直接读取脚本,从而实现了Pipeline as Code的理念。
2.Pipeline 概念
Pipeline 是一个用户定义的 CD 流水线模式。Pipeline 代码定义了通常包含构建、测试和发布步骤的完整的构建过程。
Node
node 是一个机器,它是 Jenkins 环境的一部分,并且能够执行 Pipeline。同时,node 代码块也是脚本式Pipeline 语法的关键特性。
Stage
Stage 块定义了在整个 Pipeline 中执行的概念上不同的任务子集(例如“构建”,“测试”和“部署”阶段),许多插件使用它来可视化或呈现 Jenkins 
管道状态/进度。Step一项任务。从根本上讲,一个步骤告诉 Jenkins 在特定时间点(或过程中的“步骤”)要做什么。例如,使用sh step:sh 'make' 可以执行 make 这个 shell 命令。

1. Pipeline(流水线)🍜
想象你点了一碗牛肉面,从下单到上桌的完整流程:

下单 → 煮面 → 加料 → 上桌
这就是一个典型的"流水线"。

在 Jenkins 中:

Pipeline 就是把软件从代码变成产品的完整自动化流程,包含构建→测试→部署等环节,就像面条从面粉变成美食的过程。

2. Node(节点)🔧
好比厨房里的工作台:

主厨工作台(Jenkins 服务器)

配菜工作台(其他服务器)

在 Jenkins 中:

Node 就是执行任务的机器,可以是 Jenkins 服务器本身,也可以是连接的其他电脑/服务器。

3. Stage(阶段)📦
把煮面过程拆解:

准备阶段:洗菜、切肉

烹饪阶段:煮面、熬汤

装盘阶段:摆盘、加料

在 Jenkins 中:

Stage 就是把复杂流程分成几个逻辑阶段,比如:

编译代码阶段

测试阶段

部署阶段

4. Step(步骤)🔍
煮面时的具体动作:

烧水(烧水 500ml)

下面(下面条 200g)

计时(等待 3分钟)

在 Jenkins 中:

Step 就是最小操作单元,比如:

拉取代码:git 'https://...'

运行测试:sh 'mvn test'

发送通知:slackSend '完成啦!'

举个完整的栗子 🌰
groovy
// 整个流水线在厨房工作台(node)进行
node('厨房') {
    
    // 阶段1:准备食材
    stage('备菜') {
        step('洗菜') { 水龙头.打开() }
        step('切肉') { 刀.切(牛肉, 薄片) }
    }
    
    // 阶段2:烹饪
    stage('煮面') {
        step('烧水') { 锅.加水(500ml).加热() }
        step('下面') { 锅.加(面条).煮(3min) }
    }
    
    // 阶段3:上菜
    stage('装盘') {
        step('摆盘') { 碗.放(面条).加(牛肉) }
        step('送餐') { 服务员.送到(桌号) }
    }
}
关键优势 💡
可视化流程:像看外卖进度图一样清晰

[备菜] ✅ → [煮面] ✅ → [装盘] 🟡
版本控制:菜谱(Pipeline脚本)存在Git里,随时回滚

灵活复用:同一套流程可以做:

牛肉面套餐(生产环境部署)

素面套餐(测试环境部署)

实际 Jenkins 示例 🔧
groovy
node('linux-server') {
    // 阶段1:准备代码
    stage('拉代码') {
        git 'https://github.com/myapp.git'
    }
    
    // 阶段2:打包
    stage('打包') {
        sh 'mvn clean package'
    }
    
    // 阶段3:部署
    stage('上线') {
        sh 'scp target/app.war user@prod:/opt/tomcat'
    }
}
总结 🚀
概念	生活比喻	Jenkins 作用
Pipeline	牛肉面制作流程	完整的 CI/CD 流程
Node	厨房工作台	执行任务的服务器
Stage	准备/煮/上菜	流程的逻辑阶段
Step	洗菜/切肉/烧水	具体的操作命令
简单说:Pipeline 就是用代码描述你的软件生产流水线,Jenkins 就是这条自动化流水线的总控台!
3、新建流水线项目

10、Jenkins部署分布式

如果项目需要定期集成,同时每次集成都需要较长时间。如果都运行在master服务器上,会消耗过多资源,导致其他项目搁置无法集成,这时就需要在
建立多台设备,并配置作为slave机器来为master提供负载服务。

配置的Jenkins从节点可以工作:
1、能执行git命令,拉取gitlab代码,所以要把公钥放到gitlab打通
2、执行sonar客户端的命令
3、推送到web要和web做免密钥
4、调用python脚本的权限进行通知的推送
1、部署分布式服务器
1.找一台或者目前已有的服务器配置为slave端
2.在je02上安装java jdk git和soanr客户端
yum -y install java # centos 注意版本
yum -y install git  # kylin不用安装

2.jenkins服务器操作 注意带版本号做软链接
[root@jenkins hello-world-war]# ssh-copy-id 8.138.242.118
[root@jenkins hello-world-war]# scp -r /usr/local/sonar 8.138.242.118:/usr/local/
[root@jenkins hello-world-war]# scp -r /usr/local/maven/ 8.138.242.118:/usr/local

3.与web服务器做免密钥
[root@jen02 /]# ssh-copy-id 47.111.25.47

4.将所有用到的shell脚本拷贝到je02
[root@jenkins ~]# scp deploy.sh 8.138.242.118:/root

5.jenkins服务端添加从节点je02
PS: 把je02的公钥上传至gitlab 拥有下载代码的权限
点击系统管理->节点管理->新建节点
[root@lb02:~]#ssh-keygen
[root@lb02:~]#cat .ssh/id_rsa.pub

拉取代码测试

系统管理->节点管理->新建节点

# 报错,这个错误表明 Jenkins agent 节点的 Java 版本(1.8.0_412)与 Jenkins 控制器发送的 remoting.jar 文件不兼容。
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: hudson/remoting/Launcher has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:621)
Agent JVM has terminated. Exit code=1
[05/31/25 14:08:43] Launch failed - cleaning up connection
[05/31/25 14:08:43] [SSH] Connection closed.

# 升级版本
[root@jen02 /]# yum -y install java-11-openjdk

[root@jen02 /]# alternatives --config java

There are 2 programs which provide 'java'.

  Selection    Command
-----------------------------------------------
*+ 1           java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.412.b08-1.el7_9.x86_64/jre/bin/java)
   2           java-11-openjdk.x86_64 (/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64/bin/java)

Enter to keep the current selection[+], or type selection number: 2
[root@jen02 /]# java -version
openjdk version "11.0.23" 2024-04-16 LTS
OpenJDK Runtime Environment (Red_Hat-11.0.23.0.9-2.el7_9) (build 11.0.23+9-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-11.0.23.0.9-2.el7_9) (build 11.0.23+9-LTS, mixed mode, sharing)

# 返回观察,已经正常

11、代码发布流程

1、直接发布

使用拷贝或者直接使用FTP方式进行发布代码,早期使用此种发布方式
优点: 成本较低,发布速度快,简单粗暴
缺点: 出现问题直接影响用户,回退代码较慢
适用场景:
1.开发测试场景
2.不影响用户的业务
3.初创型公司,流量较少,可以选择流量低谷期发布代码

2、金丝雀发布
1. 滚动式发布一般先发 1 台,或者一个小比例,如 2% 服务器,主要做流量验证用,类似金丝雀 (Canary) 测试。
2. 滚动式发布需要比较复杂的发布工具和智能 LB,支持平滑的版本替换和流量拉入拉出。
3. 每次发布时,先将老版本 V1 流量从 LB 上摘除,然后清除老版本,发新版本 V2,再将 LB 流量接入新版本。这样
可以尽量保证用户体验不受影响。
4. 一次滚动式发布一般由若干个发布批次组成,每批的数量一般是可以配置的(可以通过发布模板定义)。例如第一
批 1 台(金丝雀),第二批 10%,第三批 50%,第四批 100%。每个批次之间留观察间隔,通过手工验证或监控
反馈确保没有问题再发下一批次,所以总体上滚动式发布过程是比较缓慢的 (其中金丝雀的时间一般会比后续批次
更长,比如金丝雀 10 分钟,后续间隔 2 分钟)。
5. 回退是发布的逆过程,将新版本流量从 LB 上摘除,清除新版本,发老版本,再将 LB 流量接入老版本。和发布过程
一样,回退过程一般也比较慢的。
6. 滚动式发布国外术语通常叫 Rolling Update Deployment。
优点: 用户体验影响小
缺点: 发布和回滚时间比较缓慢,发布工具比较复杂,负载需要平滑的流量摘除和拉入能力
使用场景:
1.用户体验不能中断的业务
2.有一定复杂发布工具的研发能力