[笔记] 使用 Jenkins 实现 CI/CD :从 GitLab 拉取 Java 项目并部署至 Windows Server

随着软件开发节奏的加快,持续集成(CI)和持续部署(CD)已经成为确保软件质量和加速产品发布的不可或缺的部分。Jenkins作为一款广泛使用的开源自动化服务器,为开发者提供了一个强大的平台来实施这些实践。然而,在实际操作中,尤其是在需要跨越不同操作系统边界时——例如将基于Linux的构建服务器上的Java应用程序部署到Windows Server环境中——可能会遇到一系列挑战。本文聚焦于这一特定场景,详细介绍如何使用Jenkins来创建和管理Jobs,以便从GitLab仓库中拉取最新的Java项目源码,经过自动化的构建过程,最终将其部署到Windows Server上运行。

jenkins 部署 : [笔记] Jenkins 安装与配置全攻略:Ubuntu 从零开始搭建持续集成环境
前端项目部署 :[笔记] 使用 Jenkins 和 Nginx 实现前端项目的持续集成与部署 (CICD) : 从 GitLab 拉取 前端项目并部署至 Windows Server


一. 安装 jenkins 插件

1. GitLab 相关插件

用于与 GitLab 仓库集成,支持拉取代码、触发构建等。

  • GitLab
    提供 GitLab 与 Jenkins 的集成,支持 GitLab Webhook、MR 触发构建等功能。

  • Git Plugin
    用于从 Git 仓库(包括 GitLab)拉取代码。

  • GitLab API
    提供与 GitLab API 的交互支持(可选,根据需求安装)。

2. 构建工具插件

用于构建 Java 项目。

  • Maven Integration Plugin
    如果使用 Maven 构建 Java 项目,需要安装此插件。

  • Gradle Plugin
    如果使用 Gradle 构建 Java 项目,需要安装此插件。

3. SSH 相关插件

用于通过 SSH 连接到 Windows Server 2019 并部署应用。

  • SSH Build Agents Plugin
    允许 Jenkins 使用 SSH 密钥进行身份验证。

  • Publish Over SSH
    支持通过 SSH 将构建产物传输到远程服务器(Windows Server 2019)。

在这里插入图片描述


二. 全局工具配置

在这里插入图片描述

1. Maven 配置

在这里插入图片描述

2. Maven 安装

在这里插入图片描述


三. 配置代码仓库

我的代码仓库是使用的 极狐 gitlab

1. 获取 gitlab 的访问令牌(Access tokens)

在这里插入图片描述

期间 read_repository 必须勾选

  • 仅需拉取代码:
    如果 Jenkins 只需要从 GitLab 拉取代码(例如通过 Git-over-HTTP 或 Repository Files API),那么只需授予 read_repository 权限即可。
  • 需要与 GitLab API 交互:
    如果 Jenkins 需要调用 GitLab API 来进行其他操作(比如获取项目详细信息、触发构建、管理合并请求等),你将需要授予 read_api 权限。这包括对所有群组和项目的读访问权、容器镜像库和软件包库的访问权等。
  • 高级集成:
    在某些情况下,你可能还需要更多的权限,例如推送代码、创建标签或分支等。这些情况通常需要更高的权限级别,如 write_repository 或自定义权限设置。

在这里插入图片描述

2. 配置 jenkins 凭证

  • 进入凭证管理
    在这里插入图片描述
  • 配置全局凭证

在这里插入图片描述

  • 添加凭证
    在这里插入图片描述
  • 选择类型 Username with password
    在这里插入图片描述

三. (win服务器使用) Windows Server 2019 启动 OpenSSH Server

1. 安装 OpenSSH Server

# 以管理员身份运行 PowerShell# 安装 OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0# 设置自动启动
Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic# 启动 SSH 服务
Start-Service sshd
Start-Service ssh-agent# 确认服务状态
Get-Service sshd

2. 配置 SSH 服务

编辑 C:\ProgramData\ssh\sshd_config 文件,添加或修改以下内容:

# 编辑 C:\ProgramData\ssh\sshd_config 文件,添加或修改以下内容:
PasswordAuthentication yes
PermitRootLogin yes
Subsystem powershell c:/progra~1/powershell/7/pwsh.exe
KexAlgorithms diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp256
HostKeyAlgorithms ssh-rsa,rsa-sha2-512,rsa-sha2-256

3. 重启 SSH 服务

Restart-Service sshd

4. 配置防火墙

# 添加防火墙规则
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

四. 配置 SSH Servers

在这里插入图片描述

1. 使用账号密码

注意 : windows 服务器的配置 Remote Directory 只能使用基础目录 , 不可修改

在这里插入图片描述

2. 使用秘钥

a. 生成SSH密钥对

  • 打开终端或命令提示符。
  • 运行以下命令生成SSH密钥对:
# 生成 RSA 密钥对
ssh-keygen -t rsa -b 4096 -C "jenkins@example.com"# 密钥默认保存在:
# - 私钥:C:\Users\jenkins\.ssh\id_rsa
# - 公钥:C:\Users\jenkins\.ssh\id_rsa.pub
  • ssh-keygen : 用于生成、管理和转换认证密钥对的命令行工具,主要用于SSH协议。通常位于 /usr/bin/ssh-keygen/usr/local/bin/ssh-keygen
  • -t rsa-t 指定要生成的密钥类型。rsa 表示生成RSA类型的密钥。RSA是一种非对称加密算法,广泛用于SSH连接。其他常见的密钥类型包括 dsa(较少使用)、ecdsaed25519
  • -b 4096-b 指定密钥的位数。4096 表示生成的RSA密钥长度为4096位。默认情况下,ssh-keygen 生成的RSA密钥长度为2048位。增加密钥长度可以提高安全性,但也会稍微增加计算开销。4096位是一个常用的、安全的选择。
  • -C "your_email@example.com" : -C 添加一个注释(comment)到生成的公钥中。"your_email@example.com" 是你提供的注释内容,通常是你的电子邮件地址。
  • 按照提示操作,可以接受默认路径和文件名(通常是 ~/.ssh/id_rsa~/.ssh/id_rsa.pub)。
    在这里插入图片描述

  • Enter passphrase (empty for no passphrase):系统会提示你输入一个密码短语(passphrase)。如果你设置了密码短语,每次使用私钥时都需要输入它。这增加了安全性,但也增加了使用的复杂性。(如果你不希望设置密码短语,直接按回车键即可。)
    在这里插入图片描述
    在这里插入图片描述

b. 将公钥复制到 Windows Server

  • 将生成的公钥文件(通常是 ~/.ssh/id_rsa.pub)的内容复制到剪贴板。
  • 将公钥内容添加到 authorized_keys 文件
# 创建 authorized_keys 文件并添加公钥内容
# 将 Jenkins 服务器上 id_rsa.pub 的内容复制到这个文件
Add-Content -Path C:\Users\Administrator\.ssh\authorized_keys -Value "ssh-rsa AAAA..."

-Value 是你的 ~/.ssh/id_rsa.pub 的内容

在这里插入图片描述

c. 编辑 C:\ProgramData\ssh\sshd_config

# 启用公钥认证
PubkeyAuthentication yes# 指定授权密钥文件位置
AuthorizedKeysFile .ssh/authorized_keys# 可选:禁用密码认证(更安全)
PasswordAuthentication no

在这里插入图片描述

d. 设置文件权限

# 设置 .ssh 目录的权限
icacls "C:\Users\Administrator\.ssh" /inheritance:r
icacls "C:\Users\Administrator\.ssh" /grant "SYSTEM:(F)"
icacls "C:\Users\Administrator\.ssh" /grant "ADMINISTRATORS:(F)"
icacls "C:\Users\Administrator\.ssh" /grant "Administrator:(F)"# 设置 authorized_keys 文件的权限
icacls "C:\Users\Administrator\.ssh\authorized_keys" /inheritance:r
icacls "C:\Users\Administrator\.ssh\authorized_keys" /grant "SYSTEM:(F)"
icacls "C:\Users\Administrator\.ssh\authorized_keys" /grant "ADMINISTRATORS:(F)"
icacls "C:\Users\Administrator\.ssh\authorized_keys" /grant "Administrator:(F)"

e. 重启 SSH 服务

# 重启 SSH 服务
Restart-Service sshd

f. 在 Jenkins 中配置 SSH Publisher:

path to key 与 key 只需要配置一个就可以

在这里插入图片描述

3. 测试连接

在这里插入图片描述


四. 编写 jobs

在这里插入图片描述
在这里插入图片描述

1. 配置源码管理

在这里插入图片描述

2. 配置 构建完成后 上传产物与运行脚本

注意:

  1. 可以选择 构建环境中的 Send files or execute commands over SSH after the build runs 也可以选择 构建后操作中的Send build artifacts over SSH
  2. Remote directory : 我使用的是环境参数,在 Jenkins 中使用环境参数使用 必须是 ${FOLDER_NAME} 的格式。
  3. windows 服务器 运行脚本的话,只能运行服务器上的脚本。
> Exec command : 
> ${DEPLOY_BAT_PATH} "${FOLDER_NAME}" "${DEPLOY_LOG_PATH}" "${BASE_SOURCE_PATH}" "${BASE_TARGET_PATH}" "${JAR_NAME}"

在这里插入图片描述

3. 配置环境变量

在 Jenkins 中使用环境参数使用 必须是 ${FOLDER_NAME} 的格式。

parameters {// 1. 部署文件夹名称string(name: 'FOLDER_NAME',defaultValue: 'sc-wms',description: '部署文件夹名称')// 2. 日志文件路径string(name: 'DEPLOY_LOG_PATH',defaultValue: 'D:\CICD\deploy\backend\deploy.log',description: '日志文件路径')// 3. 源代码基础路径string(name: 'BASE_SOURCE_PATH',defaultValue: 'C:\Users\Administrator',description: '源代码基础路径')// 4. 目标基础路径string(name: 'BASE_TARGET_PATH',defaultValue: 'D:\CICD\project\backend',description: '目标基础路径')// 5. JAR文件名称string(name: 'JAR_NAME',defaultValue: 'mada-admin.jar',description: 'JAR文件名称')// 6. 部署脚本路径string(name: 'DEPLOY_BAT_PATH',defaultValue: 'D:\CICD\deploy\backend\deploy.bat',description: '部署脚本路径')}

在这里插入图片描述

4. 服务器项目目录结构

D:\CICD\                            # Windows 服务器上的自动化部署目录
├── deploy/                         # 部署相关
│    ├── web/                       # 前端部署相关内容
│    │    ├── deploy.bat            # 前端部署脚本
│    │    └── nginx.conf.template   # 前端项目 Nginx 配置模板
│    └── backend/                   # 后端部署相关内容
│         └── deploy.bat            # 后端部署脚本
├── nginx/                          # nginx 安装目录
│    ├── conf/                      # nginx 配置目录
│    │    ├── mime.types            # MIME 类型配置
│    │    ├── nginx.conf            # nginx 主配置
│    │    └── project_conf/         # 项目配置目录
│    ├── contrib/                   # 第三方贡献
│    ├── docs/                      # 文档
│    ├── html/                      # 网站文件目录
│    │    └── sc-wms/               # sc-wms 前端文件
│    ├── logs/                      # 日志目录
│    │    ├── access.log            # 访问日志
│    │    └── error.log             # 错误日志
│    ├── temp/                      # 临时文件目录
│    │    ├── client_body_temp/     # 客户端请求体临时文件
│    │    ├── proxy_temp/           # 代理临时文件
│    │    ├── fastcgi_temp/         # FastCGI 临时文件
│    │    ├── uwsgi_temp/           # uWSGI 临时文件
│    │    └── scgi_temp/            # SCGI 临时文件
│    └── nginx.exe                  # nginx 可执行文件
└── project/                        # 项目相关├── web/                       # 前端项目目录│    ├── sc-wms/               # sc-wms 前端项目│    │    └── dist/            # 前端构建文件│    ├── other-project/        # 其他前端项目│    └── ...                   # 更多前端项目└── backend/                   # 后端项目目录├── sc-wms/               # sc-wms 后端项目│    ├── sc-wms.jar       # 后端 jar 包│    └── start.bat        # 启动脚本├── other-project/        # 后端其他项目└── ...                   # 更多后端项目

5. 编写脚本

部分内容声明 :

# 因为一些要求 , 要生成启动的脚本 , java -jar 换成 javaw -jar 也是一样的
echo Creating start script... >> %DEPLOY_LOG%
(echo @echo offecho cd /d "%TARGET_PATH%"echo java -jar "%JAR_NAME%" ^> "%TARGET_PATH%\app.log" 2^>^&1
) > "%TARGET_PATH%\start.bat"# 这里因为...用的盗版系统,环境变量被魔改过,start不会起作用.所以用 call 了,如果可以用start用start,call会等待。导致Jenkins超时
if exist "%TARGET_PATH%\%JAR_NAME%" (:: 启动应用cd /d "%TARGET_PATH%"call start.batecho Application started successfully >> %DEPLOY_LOG%
) else (echo WARNING: JAR file not found after deployment >> %DEPLOY_LOG%
)

完整脚本:

@echo off
setlocal EnableDelayedExpansion:: 检查参数
if "%~1"=="" (echo Error: folder_name parameter is missinggoto :usage
)
if "%~2"=="" (echo Error: deploy_log_path parameter is missinggoto :usage
)
if "%~3"=="" (echo Error: base_source_path parameter is missinggoto :usage
)
if "%~4"=="" (echo Error: base_target_path parameter is missinggoto :usage
)
if "%~5"=="" (echo Error: jar_name parameter is missinggoto :usage
):: 检查并创建日志文件目录
for %%I in ("%~2") do set "LOG_DIR=%%~dpI"
if not exist "!LOG_DIR!" (echo Creating log directory: !LOG_DIR!md "!LOG_DIR!" 2>nulif errorlevel 1 (echo Error: Failed to create log directorygoto :usage)
):: 设置日志文件和基础变量
set "FOLDER_NAME=%~1"
set "DEPLOY_LOG=%~2"
set "SOURCE_PATH=%~3\%FOLDER_NAME%"
set "TARGET_PATH=%~4\%FOLDER_NAME%"
set "JAR_NAME=%~5":: 记录部署开始
echo %date% %time% - Starting Jenkins deployment > %DEPLOY_LOG%
echo Configuration: >> %DEPLOY_LOG%
echo SOURCE_PATH=%SOURCE_PATH% >> %DEPLOY_LOG%
echo TARGET_PATH=%TARGET_PATH% >> %DEPLOY_LOG%
echo JAR_NAME=%JAR_NAME% >> %DEPLOY_LOG%:: 停止现有进程
echo %date% %time% - Attempting to stop existing process... >> %DEPLOY_LOG%
taskkill /F /IM java.exe /T >> %DEPLOY_LOG% 2>&1 || echo No Java processes found >> %DEPLOY_LOG%
echo %date% %time% - Process stop attempt completed >> %DEPLOY_LOG%:: 等待进程完全停止
echo %date% %time% - Waiting for processes to stop... >> %DEPLOY_LOG%
ping -n 11 127.0.0.1 > nul
echo %date% %time% - Wait completed >> %DEPLOY_LOG%:: 清理目标目录 - 即使失败也继续
echo Cleaning target directory... >> %DEPLOY_LOG%
if exist "%TARGET_PATH%" (rd /s /q "%TARGET_PATH%" >> %DEPLOY_LOG% 2>&1
):: 创建必要目录
md "%~4" 2>nul
md "%TARGET_PATH%" 2>nul:: 复制文件
echo Moving files... >> %DEPLOY_LOG%
robocopy "%SOURCE_PATH%" "%TARGET_PATH%" /E /MOVE /R:1 /W:1 >> %DEPLOY_LOG% 2>&1:: 创建启动脚本
echo Creating start script... >> %DEPLOY_LOG%
(echo @echo offecho cd /d "%TARGET_PATH%"echo java -jar "%JAR_NAME%" ^> "%TARGET_PATH%\app.log" 2^>^&1
) > "%TARGET_PATH%\start.bat":: 验证部署
if exist "%TARGET_PATH%\%JAR_NAME%" (:: 启动应用cd /d "%TARGET_PATH%"call start.batecho Application started successfully >> %DEPLOY_LOG%
) else (echo WARNING: JAR file not found after deployment >> %DEPLOY_LOG%
)echo Deployment completed at %date% %time% >> %DEPLOY_LOG%endlocal
exit /b 0:usage
echo Usage: deploy.bat [folder_name] [deploy_log_path] [base_source_path] [base_target_path] [jar_name]
echo Example: %%FOLDER_NAME%% %%DEPLOY_LOG_PATH%% %%BASE_SOURCE_PATH%% %%BASE_TARGET_PATH%% %%JAR_NAME%%
exit /b 1

五. 运行 jobs

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/68061.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qt QPainter setViewport setWindow viewport window

使用qt版本5.15.2 引入viewport和window目的是用于实现QPainter画出来的内容随着窗体伸缩与不伸缩两种情况,以及让QPainter在widget上指定的区域(viewport)进行绘制/渲染(分别对应下方demo1,demo2,demo3)。 setViewpo…

likeshop同城跑腿系统likeshop回收租赁系统likeshop多商户商城安装及小程序对接方法

前言:首先likeshop是一个开发平台,是一个独创的平台就像TP内核平台一样,你可以在这个平台上开发和衍生出很多伟大的产品,以likeshop为例,他们开发出商城系统,团购系统,外卖点餐系统,…

C# 与 Windows API 交互的“秘密武器”:结构体和联合体

一、引言 在 C# 的编程世界里,当我们想要深入挖掘 Windows 系统的底层功能,与 Windows API 打交道时,结构体和联合体就像是两把神奇的钥匙🔑 它们能够帮助我们精准地操控数据,实现一些高级且强大的功能。就好比搭建一…

C++实现设计模式---状态模式 (State)

状态模式 (State) 状态模式 是一种行为型设计模式,它允许对象在运行时根据内部状态的改变来动态改变其行为。通过将状态相关的行为封装到独立的类中,状态模式使得状态的切换更加清晰和灵活。 意图 将对象的行为和状态分离,随着状态的改变动…

202312 青少年软件编程等级考试C/C++ 一级真题答案及解析(电子学会)

第 1 题 数的输入和输出 输入一个整数和双精度浮点数,先将浮点数保留2位小数输出,然后输出整数。 时间限制:1000 内存限制:65536 输入 一行两个数,分别为整数N(不超过整型范围),双精度浮点数F,以一个空格分开。 输出 一行两个数,分别为保留2位小数输出的F,以…

信息系统项目管理-采购管理-采购清单示例

序号类别产品/服务名称规格/功能描述数量备注1硬件服务器高性能处理器,大容量存储10HP、DELL2网络设备高速路由器和交换机10华为3工作站多核处理器,高分辨率显示器25国产设备4移动检查设备手持式移动检查仪,可连接云平台30国产设备5打印机和扫…

继续以“实用”指导Pythonic编码(re通配表达式)(2024年终总结②)

弃现成工具手剥任务🧐,我哈哈滴就像笨笨的傻大个儿😋。 (笔记模板由python脚本于2025年01月12日 23:29:33创建,本篇笔记适合熟悉正则表达式的coder翻阅) 【学习的细节是欢悦的历程】 Python官网:https://www.python.or…

Mysql学习笔记之函数

1.简介 SQL提供了很多函数,便于在查询时能够快速的进行计算或者计数等操作,下文介绍一些实际场景中常用的函数。 2.字符串函数 常用的字符串函数如下表所示: 函数名描述LENGTH(str)返回字符串的长度,以字节为单位。例如LENGTH…

pytest 参数介绍

命令行参数描述常见使用案例-v / --verbose显示每个测试用例的详细信息,包括测试名称和状态pytest -v-s / --captureno禁用输出捕获,允许 print() 输出显示pytest -s-q / --quiet安静模式,减少输出,仅显示每个测试的通过/失败结果…

10步打造完美ASP.NET、Web API和控制台应用程序文件夹结构

一、前言 在大型项目中,合理的文件夹结构是项目成功的关键之一。一个好的文件夹结构就像是一座井然有序的图书馆,每一本书(代码文件)都有其固定的位置,让人能迅速找到所需。它可以让团队成员更容易理解和维护代码&…

conntrack iptables 安全组

centos 安装yum install conntrack-tools 1. conntrack状态 NEW: 新建连接(第一次包)。 ESTABLISHED: 已建立连接,正在传输数据。 RELATED: 与已有连接相关的连接,如 FTP 数据连接。 INVALID: 无效连接,无法识别或不…

相机和激光雷达的外参标定 - 无标定板版本

1. 实现的效果 通过本软件实现求解相机和LiDAR的外参,即2个传感器之间的三维平移[x, y, z]和三维旋转[roll, pitch, yaw]。完成标定后,可将点云投影到图像,效果图如下: 本软件的优势:(1)无需特…

WPF系列九:图形控件EllipseGeometry

简介 EllipseGeometry用于绘制一个椭圆的形状。它通常与其他图形元素结合使用,比如 Path 或者作为剪切区域来定义其他元素的外形。 定义椭圆:EllipseGeometry 用来定义一个椭圆或者圆的几何形状。参与绘制:可以被用作 Path 元素的数据&…

EFCore HasDefaultValueSql (续2 HasComputedColumnSql)

前情:EFCore HasDefaultValueSql EFCore HasDefaultValueSql (续1 ValueGeneratedOnAdd)-CSDN博客 小伙伴在使用 HasDefaultValueSql 时,对相关的 ValueGeneratedOnAdd, HasComputedColumnSql 也有了疑问: HasComputedColumnSql 对于计算…

qt设置qwidget背景色无效

最近在做一个界面,有三个子窗体,于是就把各个子窗体分别做成了三个UI,再将3个UI,放到1个UI,再将那一个UI在其他窗体上进行提升。 最后就发现怎么设置qwidget的背景都没有效果。 在Qt中,如果是给Qwidget的…

【Rust学习笔记】Rust 的所有权介绍

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 博客内容主要围绕: 5G/6G协议讲解 高级C语言讲解 Rust语言讲解 文章目录 Rust中的所有权介绍1.1 一个简单的例子1.2 一个稍微复杂的例…

Centos9-SSH免密登录配置-修改22端口-关闭密码登录-提高安全性

Centos9-SSH免密登录配置-修改22端口-关闭密码登录 生成秘钥对将公钥信息存进authorized_keys测试登录查询访问记录、比对指纹更换22访问端口关闭账号密码登录生成秘钥对 生成密钥对,指定 备注 和 文件目录命令执行后,默认两次回车,不设置秘钥使用密码ssh-keygen -t rsa -b …

CentOS7下Hadoop集群分布式安装详细图文教程

1、集群规划 主机 角色 DSS20 NameNode DataNode ResourceManager NodeManager DSS21 SecondaryNameNode NameNode NodeManager DSS22 DataNode NodeManager 1.1、环境准备 1.1.1 关闭防火墙 #查看防火墙状态 firewall-cmd --state #停止…

Github 2025-01-11 Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2025-01-11统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10C项目1Swift项目1Yazi - 快速终端文件管理器 创建周期:210 天开发语言:Rust协议类型:MIT LicenseStar数量:5668 个Fork数量:122…

在 Vue 项目中使用地区级联选

在 Vue 项目中使用地区级联选择的完整流程: 1.安装依赖包,这个包提供了中国省市区的完整数据。 npm install element-china-area-data --save 2.导入数据 import { regionData } from element-china-area-data 这个包提供了几种不同的数据格式&#…