项目目的

出于管理需要,也需要在公司内部实现自动发布流程。当开发机提交SVN代码之后,自动同步到测试服务器进行测试。

系统平台:
CentOS release 6.5 (Final)             内核  2.6.32-431.23.3.el6.x86_64
svnserve, version 1.6.11 (r934486)

工作原理

当开发机提交更新之后,脚本会自动执行某段代码,将代码更新到某个副本中。如果svn服务器和WEB服务器在一台电脑中,这步操作已经完成自动发布;
如果svn服务器和web服务器不在一台电脑中,则还需要使用其他办法更新文件,同步到web服务器中。

hook简单介绍

为了方便管理员控制提交的过程 ,Subversion提供了hook机制。
当特定的事件发生时,相应的 hook会被调用,hook其实就相当于特定事件的处理函数。
每个hook会得到与它所处理的事件相关的参数,根据hook的返回值,Subversion会决定是否继续当前的提交过程

配置svnserve

创建多项目代码仓库

# mkdir -pv /mnt/svn/{back/motao_platform_dev,front/{A,B}}
# mkdir /mnt/svn/svnconf
# svnadmin create /mnt/svn/front/A
# svnadmin create /mnt/svn/front/B
# svnadmin create /mnt/svn/back/motao_platform_dev

配置集中认证与授权

# mv /mnt/svn/front/A/conf/{authz,passwd} /mnt/svn/svnconf/
# rm -f /mnt/svn/front/B/conf/{authz,passwd}
# rm -f /mnt/svn/back/motao_platform_dev/conf/{authz,passwd}

# vim /mnt/svn/front/A/conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = /mnt/svn/svnconf/passwd
authz-db = /mnt/svn/svnconf/authz
realm = share

参数realm用于指明仓库所属的认证域,默认情况下每个仓库位于不同的域(每个仓库有一个唯一的uuid),因此我们可以不设置该项,除非多个仓库需要共用同一份passwd配置。
# vim /mnt/svn/front/B/conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = /mnt/svn/svnconf/passwd
authz-db = /mnt/svn/svnconf/authz
realm = share
# vim /mnt/svn/back/motao_platform_dev/conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = /mnt/svn/svnconf/passwd
authz-db = /mnt/svn/svnconf/authz
realm = share

这里是账户密码设定

# vim /mnt/svn/svnconf/passwd
[users]

A = 123456
B = 123456
C = 123456

authz简要说明

[groups]定义用户组
组名=用户1,用户2

[/]
* = r
@groups = rw

[/project1]
* =
harry = rw
sally = r

[/project1/foo]
sally =

[/project2]
@groups1 = rw
guest = r

/表示仓库根目录,*表示所有用户,用户组前面需加上@符号,r表示可读,w表示可写,等号=右边为空则表示没有权限。
注意对于目录结构,当用户访问某个资源时,SVN会先看有没有直接针对该资源的访问控制,如果没有找到,则会继承上一级目录的访问权限,如此递推。

当我们有多个仓库时,我们会发现这些仓库的用户帐号在大多数情况下都是相同的,
因此,我们可以将passwd文件放到公共的地方,然后将所有仓库的password-db配置都指向该文件。
相应的,authz-db也可以共用一个文件,不过需要在配置具体的访问控制时指明所属的仓库,如下:

[/]
* = r
所有人对所有仓库的根目录都有读权限

[repos1:/project1]
* = r
harry = rw
只有harry对仓库repos1里的dir1有读写权限

[repos2:/project1]
* = r
sally = rw
只有sally对仓库repos2里的project1有读写权限。

本例实际配置

# vim /mnt/svn/svnconf/authz    

[aliases]
[groups]

[front/A:/]
A = rw

[front/B:/]
B = rw

[back/motao_platform_dev:/]
C = rw

SVN启动与关闭指令

# svnserve -d -r /mnt/svn
-d 表示以守护进程方式运行
-r 表示svn的根目录,如果有多个仓库,应该指向包含所有仓库的上层目录,否则其他仓库不能使用。

默认使用的端口是3690

停止SVN命令

# killall svnserve

开机启动

# vim /etc/rc.local
svnserve -d -r /mnt/svn

# chmod +x /etc/rc.local

WEB服务器发布目录

创建不同的web子目录

mkdir -pv /mnt/web/front/A
mkdir -pv /mnt/web/front/B
mkdir -pv /mnt/web/back/motao_platform_dev

SVN hooks设置

创建不同版本库的hooks

# cd /mnt/svn/front/A/hooks
# cp post-commit.tmpl post-commit
# vim /mnt/svn/front/A/hooks/post-commit

#!/bin/bash
REPOS="$1"
REV="$2"
export LANG=en_US.UTF-8
SVN=/usr/bin/svn
WEB=/mnt/web/front/A
SVN_USER=A
SVN_PASS=A123456
CURDATE=`date +%F-%T`
LOG_PATH=/var/log/svn_hook_front_A.log
$SVN update ${WEB} --username ${SVN_USER} --password ${SVN_PASS} --no-auth-cache || exit1
echo  "${WEB} Deployed by at $CURDATE,`whoami`,$REPOS,$REV" >> ${LOG_PATH}
exit 0

# chmod 777 /mnt/svn/front/A/hooks/post-commit

第二个项目
# cp post-commit /mnt/svn/front/B/hooks/post-commit
# vim /mnt/svn/front/B/hooks/post-commit

#!/bin/bash
REPOS="$1"
REV="$2"
export LANG=en_US.UTF-8
SVN=/usr/bin/svn
WEB=/mnt/web/front/B
SVN_USER=B
SVN_PASS=A123456
CURDATE=`date +%F-%T`
LOG_PATH=/var/log/svn_hook_front_B.log
$SVN update $WEB --username ${SVN_USER} --password ${SVN_PASS} --no-auth-cache
echo  "$WEB Deployed by at $CURDATE,`whoami`,$REPOS,$REV" >> ${LOG_PATH}

# chmod 777 /mnt/svn/front/B/hooks/post-commit

如果svn update 出现skipped '.' 或skipped '目录名称',尝试在服务器checkout一次后,重新提交即可
# svn checkout  svn://127.0.0.1/front/B /mnt/web/front/B/ --username B --password A123456

第三个项目
# cp post-commit /mnt/svn/back/motao_platform_dev/hooks/post-commit
# vim /mnt/svn/back/motao_platform_dev/hooks/post-commit

#!/bin/bash
REPOS="$1"
REV="$2"
export LANG=en_US.UTF-8
SVN=/usr/bin/svn
WEB=/mnt/web/back/motao_platform_dev
SVN_USER=C
SVN_PASS=A123456
CURDATE=`date +%F-%T`
LOG_PATH=/var/log/svn_hook_motao_platform_dev.log
$SVN update ${WEB} --username ${SVN_USER} --password ${SVN_PASS} --no-auth-cache || exit 1
echo  "${WEB} Deployed by at $CURDATE,`whoami`,$REPOS,$REV" >> ${LOG_PATH}
exit 0

# chmod 777 /mnt/svn/back/motao_platform_dev/hooks/post-commit

如果svn update 出现skipped '.' 或skipped '目录名称',尝试在服务器checkout一次后,重新提交即可
# svn checkout  svn://127.0.0.1/back/motao_platform_dev /mnt/web/back/motao_platform_dev/ --username C --password A123456

实现SVN提交与同步

Web服务器A目录的内容

image

开发代码机

先checkout至本机,添加2个文件,并修改index.html.txt

image

image

image

Web服务器上面的同步日志

image

更新之后的Web目录

image

发布成功