建设项目环保验收公示网站孔为民医生个人网站
随着软件开发节奏的加快,持续集成(CI)和持续部署(CD)已经成为确保软件质量和加速产品发布的不可或缺的部分。Jenkins作为一款广泛使用的开源自动化服务器,为开发者提供了一个强大的平台来实施这些实践。然而,在实际操作中,尤其是在需要跨越不同操作系统边界时——例如将基于Linux的构建服务器上的Java应用程序部署到Windows Server环境中——可能会遇到一系列挑战。本文聚焦于这一特定场景,详细介绍如何使用Jenkins来创建和管理Jobs,以便从GitLab仓库中拉取最新的Java项目源码,经过自动化的构建过程,最终将其部署到Windows Server上运行。
jenkins 部署 : [笔记] Jenkins 安装与配置全攻略:Ubuntu 从零开始搭建持续集成环境
一. 安装 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(较少使用)、ecdsa和ed25519。-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. 配置 构建完成后 上传产物与运行脚本
注意:
- 可以选择 构建环境中的
 Send files or execute commands over SSH after the build runs也可以选择 构建后操作中的Send build artifacts over SSH。Remote directory: 我使用的是环境参数,在 Jenkins 中使用环境参数使用 必须是${FOLDER_NAME}的格式。- windows 服务器 运行脚本的话,只能运行服务器上的脚本。
 
> Exec command : 
> ${DEPLOY_BAT_PATH} "${FOLDER_NAME}" "${DEPLOY_LOG_PATH}" "${BASE_SOURCE_PATH}" "${BASE_TARGET_PATH}" "${JAR_NAME}"
 

3. 配置环境变量
在 Jenkins 中使用环境参数使用 必须是
${FOLDER_NAME}的格式。
- name :
 FOLDER_NAME, defaultValue : test , description : 部署文件夹名称- name :
 DEPLOY_LOG_PATH, defaultValue : E:\deploy.log , description : 日志文件路径- name :
 BASE_SOURCE_PATH, defaultValue : C:\Users\Administrator , description : 源代码基础路径- name :
 BASE_TARGET_PATH, defaultValue : E:\project , description : 目标基础路径- name :
 JAR_NAME, defaultValue : central-server.jar , description : JAR文件名称- name :
 DEPLOY_BAT_PATH, defaultValue : E:\deploy.bat , description : 部署脚本路径

4. 编写脚本
部分内容声明 :
# 因为一些要求 , 要生成启动的脚本 , 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

