svn钩子可实现提交自动校验与部署:pre-commit强制检查注释长度或jira编号,post-commit自动更新测试服务器;需复制.tmpl模板、chmod +x赋权、正确配置路径与凭证,并通过日志和手动模拟调试。

让SVN在每次提交代码时自动检查注释规范、扫描代码质量、同步测试服务器,而不是靠人工反复提醒或手动更新。
确认钩子脚本存放位置与基础权限
进入你的SVN仓库根目录下的 hooks 子目录,例如 /svn/repo1/hooks。该目录下默认只有带 .tmpl 后缀的模板文件,如 pre-commit.tmpl 和 post-commit.tmpl。
用 cp pre-commit.tmpl pre-commit 复制出可执行脚本,同样复制 post-commit.tmpl → post-commit。
【必须执行 chmod +x pre-commit post-commit】,否则SVN服务完全不会调用它们——Apache进程无权执行,提交会静默失败或直接跳过钩子。
编写 pre-commit 脚本强制校验提交信息
方法一:基础字符长度检查(防空提交)
用 vim 或 nano 编辑 pre-commit,第一行写 #!/bin/sh,接着填入:
REPOS="$1"<br>TXN="$2"<br>SVNLOOK=/usr/bin/svnlook<br>LOGMSG=$($SVNLOOK log -t "$TXN" "$REPOS" | grep -v "^$" | wc -c)<br>if [ "$LOGMSG" -lt 8 ]; then<br> echo "Commit log message must be at least 8 characters long." 1>&2<br> exit 1<br>fi
这个脚本会拒绝所有日志少于8个可见字符的提交。注意 grep -v "^$" 是为了过滤掉纯空白行,否则 wc -c 会把换行符也算进去,导致误判。
方法二:正则匹配 JIRA 编号(对接项目管理)
在上面 if 判断前插入一行:JIRA_ID=$($SVNLOOK log -t "$TXN" "$REPOS" | head -n 1 | grep -oE '[A-Z]{2,}-[0-9]+'),然后把 if 条件改成 if [ -z "$JIRA_ID" ]; then。这样就只允许首行含类似 PROJ-123 的提交通过。
配置 post-commit 实现测试环境自动更新
第一步:确保目标 Web 目录已做过首次检出
切到你要部署的路径,比如 /var/www/html/demo,执行 svn checkout svn://localhost/repo1/trunk . --username deploy --password xxx。这步漏掉,后续 update 必然报错“Not a working copy”。
第二步:编辑 post-commit 脚本
填入以下内容(关键路径和凭证按实际替换):
#!/bin/sh<br>export LANG=en_US.UTF-8<br>REPOS="$1"<br>REV="$2"<br>SVN_PATH=/usr/bin/svn<br>WEB_PATH=/var/www/html/demo<br>LOG_FILE=/var/log/svn-deploy.log<br><br>echo "$(date): rev $REV deployed to $WEB_PATH" >> $LOG_FILE<br>$SVN_PATH update "$WEB_PATH" --username deploy --password xxx --non-interactive --no-auth-cache >> $LOG_FILE 2>&1
第三步:验证 SSH 免密(如需远程更新)
如果 Web 服务器和 SVN 不在同一台机器,post-commit 中要改用 ssh user@192.168.1.100 'cd /path && svn update'。先在 SVN 服务器上用部署账号执行 ssh-keygen,再把公钥追加到目标机的 ~/.ssh/authorized_keys,否则每次 update 都卡住等密码输入。
调试钩子脚本的三个关键动作
① 手动模拟触发:运行 ./pre-commit /svn/repo1 12345,看是否输出错误并返回非零码;
② 查看 Apache 错误日志:tail -f /var/log/httpd/error_log,钩子崩溃时唯一线索就在这里;
③ 关闭 SELinux 临时验证:执行 setenforce 0,若此时钩子突然生效,说明是 SELinux 策略拦截了 /usr/bin/svn 或 hooks 目录的执行权限。











