Jenkins 配置 Publish over SSH 自动部署项目

一、前提条件

  1. 环境准备
    • Jenkins 已安装 Publish Over SSH 插件(进入 Manage JenkinsPlugins → 搜索并安装 Publish Over SSH)。
    • 目标部署服务器(需部署项目的服务器)已开启 SSH 服务(默认端口 22,若为其他端口需单独配置)。
    • Jenkins 服务器(或容器)与目标服务器网络互通(可通过 pingtelnet <目标IP> 22 验证)。

二、配置 Jenkins 与目标服务器的 SSH 免密登录

1. 在 Jenkins 容器内生成 SSH 密钥对

由于 Jenkins 通常通过 Docker 容器运行,需进入容器内生成密钥(确保密钥由 Jenkins 服务用户持有):

bash 复制代码
# 进入 Jenkins 容器(替换容器名为实际容器名,如 "jenkins")
docker exec -it -u root jenkins /bin/bash  

# 生成 RSA 密钥对(一路回车,可选设置密钥密码 Passphrase,生产环境建议设置)
ssh-keygen -t rsa -b 2048 -C "jenkins-ssh-key"  

# 生成后密钥路径:私钥 /root/.ssh/id_rsa,公钥 /root/.ssh/id_rsa.pub  

2. 将公钥复制到目标部署服务器

方式 1:使用 ssh-copy-id 自动复制(推荐,需目标服务器支持)
bash 复制代码
# 首次连接目标服务器,需手动确认指纹(输入 "yes")并输入目标服务器密码  
ssh <目标服务器用户名>@<目标服务器IP>  # 例如:ssh appuser@172.20.113.93  

# 复制公钥到目标服务器(替换用户名和IP)  
ssh-copy-id -i ~/.ssh/id_rsa.pub <目标服务器用户名>@<目标服务器IP>  
方式 2:手动复制公钥(若 ssh-copy-id 不可用)
  1. 查看 Jenkins 容器内的公钥内容

    bash 复制代码
    cat /root/.ssh/id_rsa.pub  

    复制输出的公钥文本(以 ssh-rsa 开头)。

  2. 登录目标服务器,粘贴公钥到 authorized_keys

    bash 复制代码
    # 登录目标服务器  
    ssh <目标服务器用户名>@<目标服务器IP>  
    
    # 创建 .ssh 目录(若不存在)  
    mkdir -p ~/.ssh && chmod 700 ~/.ssh  
    
    # 编辑 authorized_keys 文件,粘贴 Jenkins 公钥  
    vi ~/.ssh/authorized_keys  # 粘贴公钥后保存退出  
    
    # 设置权限(必须,否则 SSH 会拒绝免密登录)  
    chmod 600 ~/.ssh/authorized_keys  

3. 验证 SSH 免密连接

在 Jenkins 容器内执行以下命令,确认无需密码即可登录目标服务器:

bash 复制代码
ssh <目标服务器用户名>@<目标服务器IP>  # 若直接进入目标服务器终端,说明免密配置成功  

三、Jenkins 全局配置 Publish over SSH

1. 进入配置页面

Jenkins 首页 → Manage JenkinsSystem (系统配置)→ 找到 Publish over SSH 模块。

2. 配置 SSH 服务器(目标部署服务器)

(1)配置 SSH 密钥
字段 填写说明
Passphrase 若生成密钥时设置了"密钥密码",则填写该密码;未设置则留空。
Path to key 私钥在 Jenkins 容器内的绝对路径(如 /root/.ssh/id_rsa)。
Key 直接粘贴私钥文件(id_rsa)的完整文本内容(若填写此项,Path to key 会被忽略)。

推荐配置:直接粘贴私钥内容(避免容器路径变更导致失效):

  • 在 Jenkins 容器内执行 cat /root/.ssh/id_rsa,复制完整私钥文本(从 -----BEGIN RSA PRIVATE KEY----------END RSA PRIVATE KEY-----)。
  • 粘贴到 Key 字段中。
(2)添加目标服务器信息

点击 SSH ServersAdd,配置目标部署服务器参数:

字段 填写说明
Name 自定义服务器名称(如"deploy-server-172.20.113.93",后续构建时选择)。
Hostname 目标服务器 IP 或域名(如 172.20.113.93)。
Username 目标服务器登录用户名(如 appuser)。
Remote Directory (可选)默认远程目录(若构建后步骤中未指定,会使用此目录,一般留空)。
Port SSH 端口(默认 22,若目标服务器 SSH 端口非 22,需填写实际端口,如 2222)。

高级选项(按需配置)

  • 勾选 Use password authentication, or use a different key:若不使用全局密钥,可单独指定该服务器的密钥。
  • Timeout (ms):设置 SSH 连接超时时间(默认 30000 ms,网络差时可延长)。

3. 测试 SSH 连接

点击 Test Configuration ,若显示 Success,说明目标服务器配置正确;否则检查密钥、用户名、IP 或端口是否错误。

4. 保存配置

点击页面底部 Save,完成 Publish over SSH 全局配置。

四、在项目中添加构建后部署步骤(以 Spring Boot 项目为例)

以之前的 Spring Boot 项目任务(如 project-springboot-admin)为例,添加"通过 SSH 发送构建产物并部署"的步骤。

1. 进入项目配置页面

项目任务页面 → Configure (配置)→ Post-build Actions (构建后操作)→ 点击 Add post-build action → 选择 Send build artifacts over SSH

2. 配置 SSH 部署参数

(1)选择目标服务器
  • SSH Server:从下拉列表选择在全局配置中添加的目标服务器(如"deploy-server-172.20.113.93")。
(2)配置文件传输(Transfer Set)
字段 填写说明
Source files 需传输到目标服务器的文件路径(相对于 Jenkins 项目工作区的相对路径)。 示例:dsrm-server/target/dsrm-server.jar(Spring Boot 项目打包后的 JAR 包路径)。
Remove prefix (可选)移除源文件路径的前缀(如填写 dsrm-server/target,则传输到目标服务器的文件名为 dsrm-server.jar,而非带路径的文件)。
Remote directory 目标服务器接收文件的目录(绝对路径)。 示例:/home/etc/xxxxxx/target(根据实际部署路径填写)。
Exec command 文件传输完成后在目标服务器执行的部署命令(如备份旧版本、启动新服务)。
(3)填写部署命令(Exec command)

用户提供的示例命令(需根据实际路径调整):

bash 复制代码
# 1. 备份旧版本 JAR 包(以当前时间戳命名,保留历史版本)  
mv /data/app/xxxxx.jar /data/app/xxxxx.jar-$(date +%Y%m%d%H%M%S)  

# 2. 将传输到目标服务器的新 JAR 包移动到部署目录  
mv /home/etc/xxxxxx/target/dsrm-server.jar /data/app/xxxx.jar  

# 3. 执行重启脚本(后台运行,避免 Jenkins 构建进程阻塞)  
sh -c "cd /data/app && ./restart.sh & disown"  

3. 保存项目配置

点击 Save,完成构建后部署步骤配置。

五、部署脚本(restart.sh)说明

目标服务器 /data/app/restart.sh 脚本用于停止旧服务、启动新服务,内容如下(需提前创建并赋予执行权限):

bash 复制代码
#!/bin/bash  
# 停止旧服务  
rm -f nohup.out  # 清理旧日志  
app="xxxx.jar"  # 替换为实际 JAR 包名称(如 dsrm-server.jar)  
pid=$(ps -ef | grep "$app" | grep -v grep | awk '{print $2}')  # 获取进程 ID  

if [ -n "$pid" ]; then  
    echo "Stopping old process: $pid"  
    kill -9 "$pid"  # 强制停止进程  
fi  

# 启动新服务(使用指定 JDK 路径,后台运行并输出日志)  
jdk11_path="/data/software/jdk-17/bin/java"  # 替换为目标服务器 JDK 实际路径  
nohup setsid "$jdk11_path" -jar "$app" > nohup.out 2>&1 < /dev/null &  
echo "New process started successfully"  

脚本权限设置(目标服务器执行):

bash 复制代码
chmod +x /data/app/restart.sh  # 赋予执行权限  

六、验证自动部署

1. 手动触发构建

进入项目任务页面 → Build Now,等待构建完成。

2. 查看部署日志

  • Jenkins 构建日志 :构建后点击 Console Output ,搜索 SSH: Transferred 1 file(s)(文件传输成功)和 Exec command complete(部署命令执行完成)。
  • 目标服务器日志 :登录目标服务器,查看 /data/app/nohup.out,确认新服务启动日志(如 Started XxxApplication in x.x seconds)。

七、常见问题排查

1. SSH 连接失败(日志显示 Connection refusedAuthentication failed

  • 原因:目标服务器 SSH 端口错误、公钥未正确复制、Jenkins 私钥配置错误。
  • 解决
    • 确认目标服务器 SSH 端口(默认 22),全局配置中 Port 字段是否正确。
    • 重新执行公钥复制步骤,确保目标服务器 ~/.ssh/authorized_keys 包含 Jenkins 公钥,且权限为 700(.ssh 目录)和 600(authorized_keys)。
    • 检查 Jenkins 全局配置的私钥是否完整(无多余空格或换行)。

2. 文件传输失败(日志显示 No such file

  • 原因Source files 路径错误(相对于 Jenkins 项目工作区)。
  • 解决 :在 Jenkins 项目工作区(如 /var/jenkins_home/workspace/project-springboot-admin)确认 JAR 包实际路径,调整 Source files(如 dsrm-server/target/dsrm-server.jar)。

3. 部署命令执行失败(日志显示 mv: cannot stat ...

  • 原因Remote directory 路径错误或目标服务器目录权限不足。
  • 解决
    • 登录目标服务器,确认 Remote directory(如 /home/etc/xxxxxx/target)是否存在,若不存在则创建:mkdir -p /home/etc/xxxxxx/target
    • 确保 Jenkins 登录用户(如 appuser)对目标目录有读写权限:chown -R appuser:appuser /home/etc/xxxxxx/target

4. 服务启动失败(nohup.out 日志报错)

  • 原因:JDK 路径错误、JAR 包损坏或配置文件缺失。
  • 解决
    • 检查 restart.sh 中的 jdk11_path 是否指向目标服务器实际 JDK 路径(执行 which java 确认)。
    • 手动在目标服务器执行 java -jar /data/app/xxxx.jar,查看启动错误(如依赖缺失、端口占用)。

八、总结

通过以上步骤,Jenkins 可在构建完成后自动将 Spring Boot 项目的 JAR 包通过 SSH 传输到目标服务器,并执行部署脚本完成服务重启。该流程可扩展到多服务器部署(添加多个 SSH Server)或其他项目(如 Vue 项目传输前端包到 Nginx 目录),实现全自动化部署。

相关推荐
Java 码农3 小时前
jenkins + gitlab 构建自由风格的任务
servlet·gitlab·jenkins
YounGp_oo15 小时前
一次内网开发环境访问方式的改进实践:使用 FRP 替代远程桌面
网络·ssh·frp·内网穿透·开发环境
未定义.2211 天前
第1篇:0基础入门!Python+Selenium环境搭建与第一个自动化脚本
python·功能测试·selenium·自动化·jenkins·pytest
飞翔沫沫情1 天前
关于在Jenkins 的job 中隐藏shared library 共享库相关的Git信息
运维·git·jenkins
编程大师哥1 天前
如何使用Servlet进行请求转发和重定向?
servlet
阿里超级工程师1 天前
yunedit-ssh相比jenkins和winscp的特点和优势分析
服务器·ssh·jenkins
AIGCExplore1 天前
Jenkins 自动构建编译 Spring Boot 和 Vue 项目
vue.js·spring boot·jenkins
凌冰_1 天前
Thymeleaf 一个Servlet处理多个请求(六)
servlet
食咗未1 天前
Linux SSH工具的使用
linux·网络·测试工具·ssh·远程登陆