[转载]SVN利用post-commit hooks自动同步代码到生产环境

针对SVN更新过程中遇到的速度瓶颈,本文介绍了一种通过优化post-commit脚本提高更新效率的方法。通过对更新文件的精确匹配及并行处理,大幅提升了SVN的响应速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://tech.alltosun.com/home/space.php?uid=3&do=blog&id=3103

 

我们在开发的过程将代码提交到SVN后使用SVN的hook,通过post-commit脚本,在目标文件夹根下执行svn update操作,将更新内容同步到测试环境,这样开发调试非常方便。

现在SVN库的文件数量越来越多,svn 本地的目录已经3个多G了,几十万个文件,在目标文件夹下执行svn update进行更新速度也就越来越慢了,常常提交之后SVN客户端会等几分钟没有响应,在没有响应的时间内,无法再继续提交内容。如果使用zendstudio进行提交的话,所有保存的操作都要等这个SVN提交完成才能继续。

原post-commit内容:

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

#!/bin/sh

REPOS="$1"

REV="$2"

WEB=/data/web

FRAMEWORK=/data/framework

export LC_ALL=zh_CN.UTF-8

a=`svn update $WEB $FRAMEWORK /data/conf /data/shell --username x*******i --password ******* | grep 'nginx\.conf'`

if [ -n "$a" ] then kill -HUP `cat /dev/shm/nginx.pid` fi

chown -R www.www $WEB &

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

我们主要做了以下几个工作:

1、SVN更新后,同步在/data/web、/data/framework、/data/conf、 /data/shell 4个文件夹在下执行svn update命令进行同步更新操作。

2、如果/data/conf/nginx.conf文件修改了,那么重启nginx。 3、将所有/data/web目录下的文件所有者和组都变成www。 原因在于: 1、提交的SVN的时候,4个文件在根下进行更新,文件数量巨大响应非常慢。

 2、chown的操作也是比较浪费。

解决的想法:对有变化的文件进行 svn update 这样更有效率。 解决的思路: 1、得到本次提交更新的文件。

2、在目标目录中更新指定的文件。

3、同时将指定文件所有者和组变成www。

4、使用PHP程序当shell来完成这样的工作。 最后的成果是巨大的,现在svn提交已经是飞一样的快了,要知道svn 本地的目录已经3个多G了,几十万个文件。

实现步骤: 1、得到更新的文件。通过分析我们发现post-commit脚本有两个变量 # 库的路径 REPOS="$1" # 新提交的版本号 REV="$2" 通过这样的操作就可以得到本次更新的内容与文件。

 changed=$(svnlook changed -r $REV $REPOS)

2、将得到的本次更新的内容提交给PHP脚本来处理,分析哪些文件发生变化。

/usr/local/php/bin/php-cgi -q /data/shell/svn_post_commit_resources.php "$changed" & 用PHP分析出哪些文件发生变化后,构造shell命令,由PHP调用shell命令进行更新。

3、相关脚本:最新的post-commit文件内容:

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

#!/bin/sh

# 库的路径 REPOS="$1"

# 新提交的版本号

REV="$2"

WEB=/data/web

FRAMEWORK=/data/framework

export LC_ALL=zh_CN.UTF-8

changed=$(svnlook changed -r $REV $REPOS)

log=$(svnlook log -r $REV $REPOS)

n=$'\n' /usr/local/php/bin/php-cgi -q /data/shell/svn_post_commit_resources.php "$changed" &

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

处理更新内容,执行更新命令的PHP脚本文件

svn_post_commit_resources.php 的内容:

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

<?php $files = explode("\n", $argv[1]);

 if (!is_array($files)) {$files=(array)$files;};

foreach ($files as $v) {

 // 取文件名

$f_tem = trim(substr($v, 2));

 // 取最顶层目录名

$d_tem = substr($f_tem, 0, strpos($f_tem, '/'));

 if (!in_array($d_tem, array('web', 'framework', 'conf', 'shell'))) { continue; }

 // SVN copy 对应的文件

$f_name = '/data/' . $f_tem;

$cmd = "svn update '$f_name' --username x****i --password K****$;

chown www.www '$f_name'"; exec($cmd);

 if (strpos($f_tem, 'nginx.conf')) { exec("kill -HUP `cat /dev/shm/nginx.pid`"); } }

exit(); ?>

 

<think>我们参考用户提供的引用内容,特别是引用[1][2][3],来配置SVNpost-commit钩子以触发Jenkins构建。 主要步骤: 1. 在Jenkins中配置一个需要被触发的任务,并设置身份验证令牌(Token)。 2. 在SVN服务器的仓库hooks目录下,创建或修改post-commit脚本(Windows下为post-commit.bat,Linux下为post-commit)。 3. 在post-commit脚本中,通过curl命令调用Jenkins的构建触发URL。 具体配置步骤: ### 步骤1:Jenkins任务配置 1. 打开Jenkins任务配置页面。 2. 在“构建触发器”部分,勾选“触发远程构建 (例如,使用脚本)”。 3. 在“身份验证令牌”字段中,设置一个令牌(例如:`MY_TOKEN`),并记住它。 4. 保存任务。 ### 步骤2:编写SVNpost-commit钩子脚本 根据SVN服务器的操作系统选择: #### Windows系统(post-commit.bat) 在SVN仓库的hooks目录下(如:`D:\Repositories\MyRepo\hooks`),创建或修改`post-commit.bat`文件。 以下是一个基本示例(根据引用[2]和[3]修改): ```batch @echo off setlocal enabledelayedexpansion rem 设置Jenkins的认证信息 set JENKINS_USER=admin set JENKINS_PASSWORD=admin123 rem 或者使用API Token(推荐) set JENKINS_URL=http://192.168.1.100:8080 set JOB_NAME=MyJob rem 设置Jenkins任务的身份验证令牌(在Jenkins任务中配置的) set TOKEN=MY_TOKEN rem 使用curl触发Jenkins构建 curl -X POST -u "%JENKINS_USER%:%JENKINS_PASSWORD%" "%JENKINS_URL%/job/%JOB_NAME%/build?token=%TOKEN%" ``` 注意: - 将`JENKINS_USER`和`JENKINS_PASSWORD`替换为Jenkins用户的用户名和密码(或API Token,推荐使用API Token以提高安全性)。 - 将`JENKINS_URL`替换为Jenkins服务器的URL。 - 将`JOB_NAME`替换为Jenkins任务的名称。 - 将`TOKEN`替换为在Jenkins任务中设置的令牌。 #### Linux系统(post-commit) 在SVN仓库的hooks目录下(如:`/var/svn/repos/MyRepo/hooks`),创建或修改`post-commit`文件,并赋予可执行权限(`chmod +x post-commit`)。 ```bash #!/bin/bash JENKINS_USER="admin" JENKINS_PASSWORD="admin123" # 或者使用API Token JENKINS_URL="http://192.168.1.100:8080" JOB_NAME="MyJob" TOKEN="MY_TOKEN" # 使用curl触发Jenkins构建 curl -X POST -u "$JENKINS_USER:$JENKINS_PASSWORD" "$JENKINS_URL/job/$JOB_NAME/build?token=$TOKEN" ``` ### 步骤3:测试 提交一次代码SVN仓库,观察是否触发了Jenkins构建。 ### 高级配置 1. **按目录触发不同任务**(如引用[2]所示): 如果SVN仓库中有多个项目,希望根据修改的目录触发不同的Jenkins任务,可以在钩子脚本中判断修改的目录。 Windows示例(post-commit.bat): ```batch @echo off setlocal enabledelayedexpansion rem 设置仓库路径 set REPOS=%1 set REV=%2 rem 使用svnlook获取变更的目录 for /F "delims=" %%i in ('svnlook dirs-changed %REPOS% -r %REV%') do ( set changed_dir=%%i ) rem 判断变更的目录 echo !changed_dir! | findstr "project1" > nul if !errorlevel! equ 0 ( rem 触发project1的构建 curl -X POST -u "admin:admin123" "http://192.168.1.100:8080/job/project1/build?token=TOKEN1" ) echo !changed_dir! | findstr "project2" > nul if !errorlevel! equ 0 ( rem 触发project2的构建 curl -X POST -u "admin:admin123" "http://192.168.1.100:8080/job/project2/build?token=TOKEN2" ) ``` Linux示例(post-commit): ```bash #!/bin/bash REPOS="$1" REV="$2" # 获取变更的目录 changed_dir=$(svnlook dirs-changed "$REPOS" -r "$REV") if [[ $changed_dir == *"project1"* ]]; then curl -X POST -u "admin:admin123" "http://192.168.1.100:8080/job/project1/build?token=TOKEN1" fi if [[ $changed_dir == *"project2"* ]]; then curl -X POST -u "admin:admin123" "http://192.168.1.100:8080/job/project2/build?token=TOKEN2" fi ``` 2. **安全建议**: - 在Jenkins中使用API Token代替用户密码(在Jenkins用户设置中生成)。 - 确保钩子脚本的权限安全,避免敏感信息泄露。 ### 常见问题 1. **钩子脚本不执行**: - 检查脚本是否有执行权限(Linux)。 - 检查脚本的编码(Windows下应为ANSI,避免UTF-8 BOM)。 - 检查脚本中的路径是否正确。 2. **curl命令无法访问Jenkins**: - 确保网络连通性。 - 检查Jenkins的URL和端口是否正确。 - 检查防火墙设置。 3. **Jenkins未触发构建**: - 检查Jenkins任务中配置的令牌是否与脚本中的一致。 - 检查Jenkins用户的权限。 通过以上配置,即可实现SVN提交后自动触发Jenkins构建。 §§相关问题§§ 1. 如何在Jenkins中生成API Token用于远程触发构建? 2. SVN钩子脚本中如何安全地存储Jenkins认证信息? 3. 如何调试SVNpost-commit钩子脚本? 4. 如果Jenkins构建需要传递SVN的版本号作为参数,应该如何配置?</think>### 配置 SVN Post-Commit Hook 触发 Jenkins 构建 以下是详细配置步骤(以 Windows 为例,Linux 原理相同): #### 一、Jenkins 准备 1. **生成身份验证令牌** - 进入 Jenkins 任务 → 配置 → 构建触发器 - 勾选 _"触发远程构建"_ → 输入令牌(如 `SVN_HOOK_TOKEN`)→ 保存 ```plaintext [示例] 身份验证令牌:SVN_HOOK_TOKEN ``` 2. **获取用户凭证** - 进入 `用户设置` → `API Token` → 生成新 Token(如 `1145141919810`) --- #### 二、SVN Hook 配置 1. **定位 Hook 目录** - 进入 SVN 仓库的 `hooks` 目录(如 `D:\Repositories\MyRepo\hooks`) 2. **创建 `post-commit.bat` 文件** ```batch @echo off set REPOS=%1 set REV=%2 rem Jenkins认证信息 set JENKINS_USER=admin set JENKINS_TOKEN=1145141919810 rem 用户API Token set JOB_TOKEN=SVN_HOOK_TOKEN rem 任务身份验证令牌 rem 触发构建(无参数) curl -X POST "http://%JENKINS_USER%:%JENKINS_TOKEN%@192.168.1.100:8080/job/MyJob/build?token=%JOB_TOKEN%" ``` > 替换说明: > - `192.168.1.100:8080` → Jenkins 服务器地址 > - `MyJob` → Jenkins 任务名称 > - `admin`/`1145141919810` → Jenkins 用户名/API Token 3. **高级场景:按目录触发不同任务** ```batch @echo off set REPOS=%1 set REV=%2 rem 检测修改的目录 for /F %%i in ('svnlook dirs-changed %REPOS% -r %REV%') do ( if "%%i"=="projectA/src" ( curl -u admin:1145141919810 "http://jenkins/job/ProjectA/build?token=TOKEN_A" ) if "%%i"=="projectB/docs" ( curl -u admin:1145141919810 "http://jenkins/job/ProjectB/build?token=TOKEN_B" ) ) ``` --- #### 三、验证与调试 1. **手动测试钩子** ```powershell # 在 hooks 目录执行 .\post-commit.bat "D:\Repositories\MyRepo" 123 ``` - 观察 Jenkins 是否触发构建 2. **查看日志** - Jenkins 控制台输出:`Started by remote host with address: 192.168.1.50` - SVN 日志:查看 `post-commit.log`(可在脚本中添加 `>> hook.log`) --- #### ⚠️ 关键注意事项 1. **权限问题** - 确保 SVN 服务账号有权限执行 `curl` 和访问 Jenkins - Windows 需安装 [curl for Windows](https://curl.se/windows/) 2. **安全增强** - 使用 HTTPS 代替 HTTP - 在 Jenkins 中限制触发 IP(`Manage Jenkins` → `Script Console` 配置安全策略) 3. **Linux 适配** ```bash #!/bin/bash REPOS="$1" REV="$2" curl -u admin:API_TOKEN "http://jenkins/job/MyJob/build?token=JOB_TOKEN" ``` - 需赋予执行权限:`chmod +x post-commit` --- ### 配置原理图 ```mermaid sequenceDiagram participant SVN participant Hook participant Jenkins SVN->>Hook: 提交代码 (REPOS + REV) Hook->>Jenkins: 发送 POST 请求 (curl) Jenkins->>Jenkins: 验证 token Jenkins->>Jenkins: 执行构建任务 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值