SVN配置钩子

时间:2024-03-12 12:52:00

安装测试环境:109  CentOS4.6

安装:

SVN1.32http://subversion.tigris.org/downloads/subversion-1.3.2.tar.gz
安装:
解压:#: tar zxvf subversion-1.3.2.tar.gz
依次输入./configure , make , make install 进行编译安装完成。
开启SVN服务:svnserve -d
检测服务是否开启:netstat -ntlp如果看到3690的端口正常开放了,证明SVN启动了。

一、版本库钩子

3.1 start-commit  开始提交的通知

输入参数:传递给你钩子程序的命令行参数,顺序如下:

1.  版本库路径

2.  认证过的尝试提交的用户名

3.  Depth,mergeinfo,log-revprops

3.2 pre-commit 在提交结束之前提醒

输入参数:传递给你钩子程序的命令行参数。顺序是:

1.     版本库路径

2.     提交事务的名称

3.3 post-commit  成功提交的通知

传递给你钩子程序的命令行参数,顺序为:

1.     版本库路径

2.     提交创建的修订版本号

3.4 pre-revprop-change –修订版本属性修改的通知

这个钩子在修订版本属性修改之前,正常提交范围之外被执行,不像其它钩子,这个钩子默认是拒绝所有的属性修改,钩子必须要实际存在并且返回一个零值。 

SVN如何实现钩子

在Unix平台上,这意味着要提供一个与钩子同名的脚本或程序(可能是shell 脚本,Python 程序,编译过的c语言二进制文件或其他东西)。当然,脚本模板文件不仅仅是展示了一些信息—在Unix下安装钩子最简单的办法就是拷贝这些模板,并且去 掉.tmpl扩展名,然后自定义钩子的内容,确定脚本是可运行的。

PS:一定要确保钩子脚本是可执行的。而且名称就是去掉.tmpl后的名字。另外要注意要使用SVN的钩子一定要开设权限,而且是要用运行SVN的账号进行执行这些钩子

提示
由于安全原因,Subversion版本库在一个空环境中执行钩子脚本—就是没有任何环境变量,甚至没有$PATH或%PATH%。由 于这个原因,许多管理员会感到很困惑,它们的钩子脚本手工运行时正常,可在Subversion中却不能运行。要注意,必须在你的钩子中设置好环境变量或 为你的程序指定好绝对路径

目前Subversion有已实现了五种钩子:

start-commit 
它在提交事务产生前已运行,通常用来判定一个用户是否有权提交。版本库传给该程序两个参数:到版本库的路径,和要进行提交的用户名。如果程序返回一个非零值,会在事务产生前停止该提交操作。如果钩子程序要在stderr中写入数据,它将排队送至客户端。

pre-commit 
在事务完成提交之前运行,通常这个钩子是用来保护因为内容或位置(例如,你要求所有到一个特定分支的提交必须包括一 个bug追踪的ticket号,或者是要求日志信息不为空)而不允许的提交。版本库传递两个参数到程序:版本库的路径和正在提交的事务名称,如果程序返回 非零值,提交会失败,事务也会删除。如果钩子程序在stderr中写入了数据,也会传递到客户端。

Subversion的分发版本包括了一些访问控制脚本(在Subversion源文件目录树的tools/hook-scripts目录),可以 用来被pre-commit调用来实现精密的写访问控制。另一个选择是使用Apache的httpd模块mod_authz_svn,可以对单个目录进行 读写访问控制(见“每目录访问控制”一节)。在未来的Subversion版本中,我们计划直接在文件系统中实现访问控制列表(ACLs)。

post-commit 
它在事务完成后运行,创建一个新的修订版本。大多数人用这个钩子来发送关于提交的描述性电子邮件,或者作为版本库的备份。版本库传给程序两个参数:到版本库的路径和被创建的新的修订版本号。退出程序会被忽略。 

经常提到的svn hooks是一组“外挂”脚本程序,是svn提供的一组由svn事件触发的特别有用的程序。这些程序在服务器端执行,可以提供svn之外的一些附加功能。钩子可以调用批处理文件、可执行文件或者一些类似于perl、python等的脚本。 

同步程序思路:用户提交程序到SVN,SVN触发hooks,按不同的hooks进行处理,这里用到的是post-commit,利用post-commit到代码检出到SVN服务器的本地硬盘目录,再通过rsync同步到远程的WEB服务器上。[这个思想可以考虑推广一下的!以前听同事说先提交到CVS再分发用这就行了]

(说明:因为一般的WEB站点都会有多台WEB服务器如何实现代码分发同步这个可以依据rsync进行处理的。但是钩子只需要checkout到一个地方即可。其它的WEB服务器过来同步一下即可。但对于我们来讲只需要checkout到本地硬盘即puppetmastet这台服务器的本地硬盘即可。不需要再进行分发)

好像是说使用钩子的话是要有权限之分的。那我先来进行权限分配。

----------------------SVN配置用户权限 -------------------------------------------

整理文档如下:

1.     建立SVN版本库目录(即你的SVN服务器里面的文件存放在哪个目录)

#mkdir -p /opt/svndata/repos1   

说明:svn mkdir  是其实是相当于#mkdir && svn add 操作。只差一步commit操作

Svn有许多操作是可以直接一步到位进行的!

2.     有了目录现在就可以创建SVN版本库

#svnadmin create /opt/svndata/repos1/

3.     编辑SVN的配置文件主要是权限这块的相关配置信息

#vi /opt/svndata/repos1/conf/svnserve.conf

[general]

anon-access = none

auth-access = write

password-db = passwd   #还可以指定到其它目录都是可以的

authz-db = authz

realm = repos1

4.     配置允许访问SVN的用户

#vi /opt/svndata/repos1/conf/passwd

[users]

test = test

5.     配置用户访问权限相关

#vi /opt/svndata/repos1/conf/authz

[groups]

admin = test

# harry_and_sally = harry,sally

[/]

@admin = rw

[repos1:/abc/aaa]

@admin = r

版本库目录格式:
[<版本库>:/项目/目录]    #是以项目名作为第一个单位。试想肯定是以项目为单元的
@<用户组名> = <权限>
<用户名> = <权限>

其中,方框号内部分可以有多种写法:
/,表示根目录及以下。根目录是svnserve启动时指定的,我们指定为/opt/svndata。这样,/就是表示对全部版本库设置权限。
repos1:/,表示对版本库1设置权限
repos2:/abc, ,表示对版本库2中的abc项目设置权限
repos2:/abc/aaa, ,表示对版本库2中的abc项目的aaa目录设置权限

权限主体可以是用户组、用户或*,用户组在前面加@,*表示全部用户。权限可以是w、r、wr和空,空表示没有任何权限。

6.     启动svnserve -d -r /opt/svndata/  

其中:
-d表示以daemon方式(后台运行)运行
-r /opt/svndata指定根目录是/opt/svndata

7.     现在有了仓库了就可以往仓库里面提交东西了。我们是以一个项目为单位的进行提交

#mkdir -p /var/www/dotproject  项目文件目录是在这。项目名称为dotproject

#svn import -m \'project\' /var/www/dotproject svn://192.168.0.109/repos1

这个时候就会让你输入用户名与密码了

8.     从版本库中checkout东西

#mkdir myproj  && cd myproj  表示全部的项目都存在这个目录下面

#svn checkout svn://192.168.1.109/repos1 dotproect  表示把repos1里面的项目搞出来。

以上操作成功!以下是操作总结

1. #mkdir -p /opt/svndata/repos1

#svnadmin create /opt/svndata/repos1/

这样的话我们的SVN仓库的名称其实就是repos1  这个非常有用。在定义权限的时候有用

2. [repos1:/abc/aaa]   其中abc表示的是项目名称。像上面就是dotproject这个名称

@admin = r      表示这个组的用户可以进行读的权限

1.     svnserve -d -r /opt/svndata/    

-r /opt/svndata指定根目录是/opt/svndata #这个也非常有用!(哦明白了这个其实跟JSP里面的根目录一个效果如果指定了WEB项目的根目录了其实后面的文件或目录都是相对于这个根目录进行访问的。这里面如果我们指定了其实仓库的根目录的话后面的文件访问其实也是依据这个根目录进行的其中的 -d 参数表示 svnserve.exe 将会作为一个服务程序运行在后台,而 -r 参数表示将 D:\svn 目录指定为代码库的根目录。这样,当客户端使用类似 svn://192.168.0.1/foo 这样内容的 URL 来访问服务器时候,其所访问到的真实代码库,其实就是 D:\svn\foo)

3. svn import -m \'project\' /var/www/dotproject svn://192.168.0.109/repos1

   其中这里面的dotproject就是项目名称了!

2.     svn checkout svn://192.168.1.109/repos1 dotproect  #表示将这个仓库中的这个项目提取出来

看我测试权限:

# vi /opt/svndata/repos1/conf/authz

[groups]

admin = test

[repos1:/dotproject/]

@admin = r               #让这个用户只有读的权限

现在到项目目录下面就不可以再commit动作了

--no-auth-cache –username rory --password 8809117 

1.     我编辑/opt/svndata/repos1/hooks/ pre-commit  这个文件里面的内容如下:

#!/bin/bash

REPOS="$1"

TXN="$2" 

# Make sure that the log message contains some text.

SVNLOOK=/usr/local/bin/svnlook

$SVNLOOK log -t "$TXN" "$REPOS" | \

   grep "[a-zA-Z0-9]" > /tmp/aaa || exit 1 

# Check that the author of this commit has the rights to perform

# the commit on the files and directories being modified.

# commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 

# All checks passed, so allow the commit.

exit 0         #返回0表示允许提交?

运行这段程序正常了!

然后我将其换成我自己的脚本看:(这台正常了哦哦!)

#!/bin/bash

/bin/echo "a" >> /tmp/aaa.out      成功记录日志

# exit 1 

#REPOS="$1"

#TXN="$2" 

# Make sure that the log message contains some text.

#SVNLOOK=/usr/local/bin/svnlook

#$SVNLOOK log -t "$TXN" "$REPOS" | \

#   grep "[a-zA-Z0-9]" > /tmp/aaa || exit 1 

# Check that the author of this commit has the rights to perform

# the commit on the files and directories being modified.

# commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 

# All checks passed, so allow the commit.

exit 0

 -rwxr-xr-x  1 root root  494 Nov  1 13:21 pre-commit

 OK我们现在来写一个成功svn-commit之后要触发的一个钩子

#!/bin/bash

REPOS="$1"

TXN="$2"

/bin/echo "eeeee" >> /tmp/dddddsvn.out   成功!

 OK!现在换一个python脚本来试试

我想让SVN在提交之后执行一段python程序

#!/usr/bin/env python   #这一段的意义就是当将这个python程序置成可执行时候。它会去哪寻找python。如果没有这段的话将其设置成可执行的时候就不会跑起来

if __name__ == \'__main__\':

   import sys,string

   try:

     logfile = open(\'/tmp/python.out\',\'a+\')  #简单写个日志记录一下

     logfile.write("this is a python hook")

     logfile.close()

   except:

     exit(1)

   sys.exit(0)

 然后在post-commit里面的代码如下:

#!/bin/bash

REPOS="$1"

TXN="$2"

/usr/bin/python /opt/svndata/repos1/hooks/so.py  #直接调用这段python程序

 OK!现在来编写SVNUPDATE这块的代码。

实现原理:当用户提交commit动作发生都让另外一处project马上从仓库中进行代码checkout一份出来! 

说明:post-commit会接受两个参数

REPOS="$1"      /opt/svndata/repos1  表示svn仓库的绝对路径值

TXN="$2"         表示最新的一个版本号。最后一个版本号

来看看update的相关参数项

对它的描述如下:

Svn update会把版本库的修改带到工作拷贝(工作拷贝的理解其实就是一个工作区)中。如果没有给定修订的版本它就会把当前的工作拷贝更新到HEAD最新版本。否则就是它会把工作拷贝更新到指定的修订版本即—revision后面所带的参数值。为了保持同步svn update也会删除所有在工作拷贝发现的无效锁定。 

正式的代码如下:

#vi /opt/svndata/repos1/hooks/post-commit

#!/bin/bash

/usr/local/bin/svn  update /home/myproject/dotproect/ --username test --password test

if [ $? == 0 ]

then

        echo "ok" >> /tmp/z.out

fi

    测试发现当我修改一个文件然后再commit提交的时候另外一个项目位置是可以。 

现在正式搭建SVN的环境。包括用户权限相关的内容!

--------------------------搭建puppet与svn环境--------------------------------

环境:108

项目名称:puppet

项目代码目录:mkdir -p /var/www/puppet  (将/etc/puppet下面的东西先cp过来)

代码仓库名称:repos1

仓库的目录:mkdir -p /opt/svndata/repos1

到时会在/etc/ 下面进行一次一次checkout将项目直接checkout到etc目录下面

#svn checkout svn://192.168.0.109/repos1 puppet   #表示将这个项目直接checkout下来(可以先在一个目录进行测试下看看)

具体步骤如下:

整理文档如下:

9.     建立SVN版本库目录(即你的SVN服务器里面的文件存放在哪个目录)

#mkdir -p /opt/svndata/repos1   

说明:svn mkdir  是其实是相当于#mkdir && svn add 操作。只差一步commit操作

Svn有许多操作是可以直接一步到位进行的!

10.  有了目录现在就可以创建SVN版本库

#svnadmin create /opt/svndata/repos1/

11.  编辑SVN的配置文件主要是权限这块的相关配置信息

#vi /opt/svndata/repos1/conf/svnserve.conf

[general]

anon-access = none

auth-access = write

password-db = passwd   #还可以指定到其它目录都是可以的

authz-db = authz

realm = repos1

12.  配置允许访问SVN的用户

#vi /opt/svndata/repos1/conf/passwd

[users]

test = test

13.  配置用户访问权限相关

#vi /opt/svndata/repos1/conf/authz

[groups]

admin = test

# harry_and_sally = harry,sally

[/]

@admin = rw

[repos1:/abc/aaa]

@admin = r

版本库目录格式:
[<版本库>:/项目/目录]    #是以项目名作为第一个单位。试想肯定是以项目为单元的
@<用户组名> = <权限>
<用户名> = <权限>

其中,方框号内部分可以有多种写法:
/,表示根目录及以下。根目录是svnserve启动时指定的,我们指定为/opt/svndata。这样,/就是表示对全部版本库设置权限。
repos1:/,表示对版本库1设置权限
repos2:/abc, ,表示对版本库2中的abc项目设置权限
repos2:/abc/aaa, ,表示对版本库2中的abc项目的aaa目录设置权限

权限主体可以是用户组、用户或*,用户组在前面加@,*表示全部用户。权限可以是w、r、wr和空,空表示没有任何权限。

14.  启动svnserve -d -r /opt/svndata/  

其中:
-d表示以daemon方式(后台运行)运行
-r /opt/svndata指定根目录是/opt/svndata

15.  现在有了仓库了就可以往仓库里面提交东西了。我们是以一个项目为单位的进行提交

#mkdir -p /var/www/puppet    项目文件目录是在这。项目名称为dotproject

#svn import -m \'project\' /var/www/puppet  svn://192.168.0.109/repos1

这个时候就会让你输入用户名与密码了(注意passwz里面不要有前缀空格)

16.  从版本库中checkout东西

(先:#rm –rf /puppet/)将puppet目录先删除掉。再执行这一条命令。我觉得这太绕了!!!这样的话就会有这个目录而且这里面的文件均进来了!

#svn checkout svn://192.168.0.109/repos1 puppet  表示把repos1里面的项目搞出来。

17.  编写这个SVN的钩子

#!/bin/bash

/usr/local/bin/svn  update /home/myproject/dotproect/ --username test --password test

if [ $? == 0 ]

then

echo "ok" >> /tmp/z.out

fi

----------------然后就可以在WINDOWS平台连接过来。进行操作然后直接SVN提交。 

--------------------------高级应用篇-----------------------------------------

1.     如何精确地进行用户权限划分

示例:对于modules目录里面的划分非常强烈。比如apache/  mysql/目录其中mysql用户只能管理mysql里面的东西。Apache用户只能管理apache里面东西

WIN平台要想让TV不记密码可以将:

C:\Documents and Settings\Administrator\Application Data\Subversion\auth里面的全部文件给删除掉即可!

Authz文件配置如下:

[groups]

admin = test

db = mysql

www = apache

[repos1:/]

test = rw

[repos1:/modules/mysql]

mysql = rw

*=

[repos1:/modules/apache]            原来上面的写法说第一节表示项目名称是错了。

apache = rw

*=

这样一写我就可以控制某个目录某个用户的访问权限了!将来puppet本身的配置文件管理是可以这样进行细分的! 

2.     如果将一个目录删除掉了如何同步呢?

假设你使用Windows的客户端TortoiseSVN,你可以这样操作:
1。在工作目录下,选中要删除的文件和目录.
2。右键,点击菜单TortoiseSVN -> Delete,这时会看到那些文件已经没了
3。然后执行commit,会看到在提交对话框中出现了那些删除文件
提交后,这些文件和目录就被删除了
其它开发者update一下,他们工作目录的那些文件也相应地被删除

优点:在操作时看不到多余的文件,版本号保留了

缺点:库大小还是没有变 

使用命令操作如下:

#svn delete test        将这个文件或目录给删除掉

#svn commit -m \'delete test\' 将其提交一下 

现在换到客户端进行删除文件

按照上面的说法进行操作成功将文件删除掉!

------------------------到此!成功配置完成SVN+PUPPET---------------------------

(全文完.)