Jenkins Publish Over SSH 插件配置指南
Jenkins 访问入口
- 统一入口:
https://ruoyioffice.com/jenkins/ - Jenkins 以
--prefix=/jenkins运行,系统配置中的 Jenkins URL 必须同为https://ruoyioffice.com/jenkins/。 - 公网不再开放旧的 HTTP
:14080管理入口;Nginx 在 HTTPS 站点内反代到内网 Jenkins。 - 若出现静态资源 404、登录后跳转到根路径或 crumb 校验失败,先确认上面两个 URL/prefix 配置完全一致。
插件优势
使用 Publish Over SSH 插件相比直接使用 SSH 命令有以下优势:
- 配置集中管理:SSH 连接信息统一在 Jenkins 系统配置中管理,多个任务可复用
- 更简洁的 Pipeline:无需在 Jenkinsfile 中处理 SSH 密钥和连接细节
- 更好的日志输出:自动显示文件传输进度和详细信息
- 自动重试机制:传输失败时可自动重试
- 支持多服务器:可以同时部署到多台服务器
- 图形化配置:通过 Web 界面配置,更直观易用
安装步骤
1. 安装 Publish Over SSH 插件
- 登录 Jenkins Web 界面
- 进入
Jenkins管理->插件管理 - 点击
可选插件标签页 - 在搜索框中输入
Publish Over SSH - 找到
Publish Over SSH Plugin - 勾选该插件,点击
直接安装或下载待重启后安装 - 等待插件安装完成(可能需要重启 Jenkins)
2. 配置 SSH 服务器
2.1 准备 SSH 私钥
在 Jenkins 服务器上获取 SSH 私钥内容:
bash
# 方式1: 从容器内获取
docker exec jenkins cat ~/.ssh/jenkins_rsa
# 方式2: 从宿主机挂载目录获取
cat /opt/jenkins_home/.ssh/jenkins_rsa
# 方式3: 使用提供的脚本
chmod +x get-jenkins-ssh-key.sh
./get-jenkins-ssh-key.sh重要: 复制完整的私钥内容,包括:
-----BEGIN OPENSSH PRIVATE KEY-----或-----BEGIN RSA PRIVATE KEY------ 中间的所有行(无空行)
-----END OPENSSH PRIVATE KEY-----或-----END RSA PRIVATE KEY-----
2.2 在 Jenkins 中配置 SSH 服务器
- 进入
Jenkins管理->系统配置 - 滚动到
Publish over SSH部分 - 点击
新增按钮添加 SSH 服务器
配置参数:
| 参数 | 值 | 说明 |
|---|---|---|
| Name | nginx-server | 服务器配置名称(在 Jenkinsfile 中引用) |
| Hostname | 127.0.0.1 | Nginx 服务器 IP 地址 |
| Username | root | SSH 登录用户名 |
| Remote Directory | /data/nginx/html | 远程基础目录(所有传输的相对路径基于此目录) |
高级配置(点击 高级 按钮):
| 参数 | 值 | 说明 |
|---|---|---|
| Use password authentication | 不勾选 | 使用密钥认证 |
| Passphrase | 留空 | 如果私钥有密码,在此填写 |
| Key | 粘贴私钥内容 | 完整的 SSH 私钥(见上方准备步骤) |
| Port | 22 | SSH 端口(默认 22) |
| Timeout (ms) | 300000 | 连接超时时间(毫秒,默认 300000 = 5分钟) |
2.3 测试连接
点击
Test Configuration按钮如果显示
Success,说明配置正确如果失败,检查:
- 私钥格式是否正确(无空行)
- 远程服务器是否配置了 authorized_keys
- 网络是否互通
- 用户名和端口是否正确
点击
保存保存配置
Jenkinsfile 配置
环境变量配置
groovy
environment {
// VitePress 构建产物目录
DIST_DIR = 'docs/.vitepress/dist'
// 远程服务器配置名称(对应 Publish Over SSH 插件中的配置名)
REMOTE_SERVER = 'nginx-server'
// Nginx 部署目录(相对于 Publish Over SSH 配置的远程目录)
DEPLOY_PATH = 'ruoyi-office-doc'
}部署阶段配置
groovy
stage('5. 部署到 Nginx') {
steps {
echo '🚚 开始部署到远程服务器...'
sshPublisher(
publishers: [
sshPublisherDesc(
configName: env.REMOTE_SERVER,
transfers: [
sshTransfer(
cleanRemote: true, // 清理远程目录
sourceFiles: "${DIST_DIR}/**", // 要上传的文件
removePrefix: env.DIST_DIR, // 去掉路径前缀
remoteDirectory: env.DEPLOY_PATH // 远程目录
)
]
)
]
)
}
}参数说明
sshPublisher 参数
| 参数 | 类型 | 说明 |
|---|---|---|
publishers | Array | SSH 发布配置列表(可配置多个服务器) |
sshPublisherDesc 参数
| 参数 | 类型 | 说明 |
|---|---|---|
configName | String | SSH 服务器配置名称(对应系统配置中的 Name) |
transfers | Array | 文件传输配置列表 |
verbose | Boolean | 是否显示详细日志(默认 false) |
sshTransfer 参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
sourceFiles | String | - | 要上传的文件(支持通配符,如 dist/**) |
removePrefix | String | - | 去掉路径前缀(如 dist,上传时不带此目录) |
remoteDirectory | String | - | 远程目录(相对于 SSH Server 配置的 Remote Directory) |
cleanRemote | Boolean | false | 是否清理远程目录(谨慎使用) |
excludes | String | - | 排除的文件(支持通配符) |
flatten | Boolean | false | 是否展平目录结构 |
makeEmptyDirs | Boolean | false | 是否创建空目录 |
execTimeout | Integer | 120000 | 执行超时时间(毫秒) |
完整示例
部署到单台服务器
groovy
sshPublisher(
publishers: [
sshPublisherDesc(
configName: 'nginx-server',
transfers: [
sshTransfer(
cleanRemote: true,
sourceFiles: 'docs/.vitepress/dist/**',
removePrefix: 'docs/.vitepress/dist',
remoteDirectory: 'ruoyi-office-doc'
)
],
verbose: true
)
]
)部署到多台服务器
groovy
sshPublisher(
publishers: [
sshPublisherDesc(
configName: 'nginx-server-1',
transfers: [
sshTransfer(
sourceFiles: 'dist/**',
removePrefix: 'dist',
remoteDirectory: 'app'
)
]
),
sshPublisherDesc(
configName: 'nginx-server-2',
transfers: [
sshTransfer(
sourceFiles: 'dist/**',
removePrefix: 'dist',
remoteDirectory: 'app'
)
]
)
]
)传输后执行命令
groovy
sshPublisher(
publishers: [
sshPublisherDesc(
configName: 'nginx-server',
transfers: [
sshTransfer(
sourceFiles: 'dist/**',
removePrefix: 'dist',
remoteDirectory: 'app',
execCommand: '''
echo "部署完成"
docker exec nginx nginx -s reload
'''
)
]
)
]
)故障排查
1. 测试连接失败
问题: 点击 Test Configuration 显示失败
排查步骤:
检查私钥格式:
bash# 确保私钥无空行 cat ~/.ssh/jenkins_rsa | grep -v '^$'检查 authorized_keys:
bash# 在 Nginx 服务器上执行 cat /root/.ssh/authorized_keys chmod 700 /root/.ssh chmod 600 /root/.ssh/authorized_keys手动测试 SSH 连接:
bash# 在 Jenkins 服务器上执行 ssh -i ~/.ssh/jenkins_rsa root@127.0.0.1
2. 文件传输失败
问题: 构建时文件传输失败
排查步骤:
检查远程目录权限:
bash# 在 Nginx 服务器上执行 ls -la /data/nginx/html chmod 755 /data/nginx/html检查源文件是否存在:
groovysh "ls -la ${DIST_DIR}"启用详细日志:
groovysshPublisherDesc( configName: 'nginx-server', verbose: true, // 启用详细日志 ... )
3. 远程目录路径问题
问题: 文件上传到错误的目录
说明:
Remote Directory(系统配置):/data/nginx/htmlremoteDirectory(Jenkinsfile):ruoyi-office-doc- 最终路径:
/data/nginx/html/ruoyi-office-doc
验证:
bash
# 在 Nginx 服务器上检查
ls -la /data/nginx/html/ruoyi-office-doc对比:Publish Over SSH vs 直接 SSH
| 特性 | Publish Over SSH | 直接 SSH 命令 |
|---|---|---|
| 配置复杂度 | 低(图形化配置) | 高(需要处理密钥、命令) |
| 代码可读性 | 高(声明式配置) | 中(命令式脚本) |
| 错误处理 | 自动处理 | 需要手动处理 |
| 日志输出 | 详细且格式化 | 需要手动格式化 |
| 多服务器部署 | 简单(配置多个 publisher) | 复杂(需要循环或重复代码) |
| 学习曲线 | 平缓 | 陡峭 |
| 灵活性 | 中(受插件限制) | 高(可执行任意命令) |
推荐配置
对于当前项目(VitePress 文档部署),推荐使用 Publish Over SSH 插件:
✅ 优势:
- 配置简单,易于维护
- 日志清晰,便于排查问题
- 支持自动清理远程目录
- 无需在 Jenkinsfile 中处理 SSH 密钥
⚠️ 注意事项:
- 需要额外安装插件
- 首次配置需要一定时间
- 私钥格式必须正确(无空行)
总结
使用 Publish Over SSH 插件可以大大简化部署流程,使 Jenkinsfile 更加清晰易读。建议按照本文档完成配置后,使用新的 Jenkinsfile 进行部署。
