做为新一代的开源版本控制工具,Subversion 以其目录版本化、原子提交、版本化的元数据、更加有效的分支和标签等优良特性,正逐渐受到开源软件社区的重视,并有望取代 CVS,成为开源软件开发中版本控制的首选系统。在服务端,Subversion 最大的独特之处,在于它能够经过一个扩展模块与 Apache 的HTTP 服务器相结合,实现不少高级的管理功能和安全特性。与 CVS 相比,Subversion 实现了更加先进和安全的用户认证功能。在Apache 的支持下,用户能够经过 HTTP 协议访问版本库,管理员能够对用户访问 HTTP 的权限作出具体的设置,同时 Subversion还能够得到 SSL传输加密,用户数据加密,以及目录级的访问控制等特性。java
本文将在服务器端配置工做的角度,结合做者在实际开发工做当中的配置实例,介绍 Subversion 服务器端的基本配置和管理,以及如何将 Subversion 与 Apache 结合,实现一些高级管理功能。mysql
在开源软件的开发过程中,因为开发方式自由和开发人员分散这些特性,版本控制问题一直是关系到项目成败的重要问题。没有版本控制系统的支持,开源软件的开发过程就是混乱和不可控制的。sql
长期以来,CVS 做为一种广泛采用的开源版本控制工具,在不少的开源软件项目当中充当了重要的角色。在 Eclipse 当中,更是把 CVS做为一个默认的插件,与 Ant,JUnit 等工具并列在一块儿,成为 Eclipse 软件开发的基本工具。近年来,随着开源社区的发展,一种功能更增强大的开源版本控制工具逐渐进入了人们的视野,那就是 Subversion,凭借着更为优秀的特性,Subversion 正在逐步取代 CVS,成为新一代的开源版本控制工具。数据库
相比 CVS,Subversion 中的目录、文件以及更名等元数据都是被版本化的,例如文件的更名、拷贝等等操做;并且,在 Subversion中,提交操做是不可分割的,修订版本号是基于每次提交操做而非文件;另外,Subversion 能够独立运行,有着轻量级的分支(Branching)与标签(Tagging)操做,版本库能够采用数据库(BerkeleyDB)或者是使用特定格式的文件进行存储,对二进制文件进行处理更为有效;最后,Subversion工具以及相关插件都有着很好的国际化支持,能够支持包括简体中文在内的多种语言版本,方便全球各地的开发人员。这些优秀的新特性,使得 Subversion 成为开源社区目前的最佳选择。apache
对于普通用户,即应用程序开发者而言,尤为是对 Eclipse 的用户而言,Subversion 的使用十分的简单。经过官方提供的 Eclipse 插件 Subclipse,用户能够在 Eclipse 里面很方便的使用 Subversion 客户端的各项基本功能。具体的客户端设置和使用方法,请参考 Subversion 官方网站和 Subclipse 官方网站。简单说来,在 Eclipse 中使用 Subversion 插件的基本功能,如更新、提交、同步、分支等等,基本上同使用 Eclipse 自带的 CVS 插件如出一辙,这样,用户就能够从 CVS 方便的转移到 Subversion。浏览器
目前,Subversion 已经升级到 1.3.2 版本,相关下载、特性说明和详细使用手册能够在 Subversion 主页上找到。安全
有了简单易用的客户端,大部分的用户均可以轻松使用 Subversion 了,不过,做为服务器端的管理人员,还必须进一步了解服务器端的基本配置管理,才能够充分利用 Subversion 的各项优秀特性。服务器
Subversion 的版本库(repository),就是位于服务器端,统一管理和储存数据的地方。本文中,咱们以 Linux 为例,介绍在服务器端配置和管理 Subversion 版本库的基本方法。网络
要建立一个版本库,首先要肯定采用哪一种数据存储方式。在 Subversion 中,版本库的数据存储有两种方式,一种是在 Berkeley DB数据库中存放数据;另外一种是使用普通文件,采用自定义的格式来储存,称为 FSFS。dom
两种存放方式各有优缺点,读者能够参考 http://svnbook.org/上面的文档来了解二者详细的比较和区别,这里,咱们仅引用上述文档当中的简单对照表,给出一个简明的比较。
特性 | Berkeley DB | FSFS |
---|---|---|
对操做中断的敏感 | 很敏感;系统崩溃或者权限问题会致使数据库“塞住”,须要按期进行恢复。 | 不敏感 |
可只读加载 | 不能 | 能够 |
存储平台无关 | 不能 | 能够 |
可从网络文件系统访问 | 不能 | 能够 |
版本库大小 | 稍大 | 稍小 |
扩展性:修订版本树数量 | 无限制 | 某些本地文件系统在处理单一目录包含上千个条目时会出现问题。 |
扩展性:文件较多的目录 | 较慢 | 较慢 |
检出最新代码的速度 | 较快 | 能够 |
大量提交的速度 | 较慢,但时间被分配在整个提交操做中 | 较快,但最后较长的延时可能会致使客户端操做超时 |
组访问权处理 | 对于用户的 umask 设置十分敏感,最好只由一个用户访问。 | 对 umask 设置不敏感 |
功能成熟时间 | 2001 年 | 2004 年 |
肯定了具体的数据存储类型,只要在命令行当中执行 svnadmin
命令就能够建立一个 Subversion 版本库,命令以下
# 建立文件夹 $ mkdir /etc/svn/ $ mkdir /etc/svn/repos # 运行建立版本库的命令,指定数据存储为 FSFS,若是要指定为 Berkeley DB,则将 fsfs 替换为 bdb $ svnadmin create --fs-type fsfs /etc/svn/repos
若是一切正常,命令执行后不会有任何反馈信息而迅速返回,这样,一个新的版本库就被建立出来了。咱们来查看一下生成的版本库结构:
$ ls -l /etc/svn/repos 总用量 56 drwxrwxr-x 2 robert robert 4096 8月 27 17:27 conf drwxrwxr-x 2 robert robert 4096 8月 27 17:27 dav drwxrwsr-x 5 robert robert 4096 8月 27 17:27 db -r--r--r-- 1 robert robert 2 8月 27 17:27 format drwxrwxr-x 2 robert robert 4096 8月 27 17:27 hooks drwxrwxr-x 2 robert robert 4096 8月 27 17:27 locks -rw-rw-r-- 1 robert robert 229 8月 27 17:27 README.txt
其中,conf 目录下存放了版本库的配置文件,包括用户访问控制和权限控制等内容,文件自己的注释说明十分详细,读者能够根据注释自行配置;dav 目录是提供给 Apache 相关模块的目录,目前为空;db 目录下存放着 Subversion所要管理的全部受版本控制的数据,不一样的存储方式(Berkeley DB 或者FSFS)下有着不一样的目录结构,不过咱们通常不用直接修改和查看这个目录下的内容,Subversion 的命令能够安全的操做这个目录;另外,hooks目录存放着钩子脚本及其模版(一种版本库事件触发程序),locks 目录存放着 Subversion 版本库锁定数据,format文件记录了版本库的布局版本号。
有了新建的版本库, 就能够往里面添加项目了。不过,管理员必须考虑的问题是,应该将每个项目分别放在不一样的版本库里面,仍是应该将它们放在统一的版本库里面。统一的版本库 可让管理员更加容易的升级和备份,不过,因为访问权限控制是针对整个版本库的,因此,统一的版本库也为不一样项目配置不一样的访问权限带来了麻烦。因此,管 理员应该根据实际状况权衡考虑。
咱们以统一的版本库为例,添加两个项目 project_luni 和 project_test。要作到这个,最好的办法就是用 svn import
命令导入已有的目录树。
首先,咱们在一个临时目录下,根据 Subversion 版本控制的通常布局结构,建立出两个项目的主要目录树,以下:
/etc/svn/tmp | ――project_luni | | | ――branches | | | ――tags | | | ――trunk | ――project_test | ――branches | ――tags | ――trunk
而后,用 svn import
命令来进行项目的导入:
$ svn import /etc/svn/tmp/ file:///etc/svn/repos/ --message "init" 新增 /etc/svn/tmp/project_test 新增 /etc/svn/tmp/project_test/trunk 新增 /etc/svn/tmp/project_test/branches 新增 /etc/svn/tmp/project_test/tags 新增 /etc/svn/tmp/project_luni 新增 /etc/svn/tmp/project_luni/trunk 新增 /etc/svn/tmp/project_luni/branches 新增 /etc/svn/tmp/project_luni/tags 提交后的修订版为 1。
做为版本库管理员,咱们常常须要查看 Subversion 版本库的情况,这就须要一些“只读”的查看工具。
在上述项目导入完成之后,咱们能够用 svn list
确认导入的项目是否正确:
$ svn list --verbose file:///etc/svn/repos/ 1 robert 8月 27 18:24 project_luni/ 1 robert 8月 27 18:24 project_test/
另外,若是要查看最新修订版本的信息,可使用 svnlook info
命令:
$ svnlook info /etc/svn/repos/ robert 2006-08-27 18:24:27 +0800 (日, 27 8月 2006) 0
命令输出了这个版本库的最新修订版本信息,包括做者、时间、日志字数和日志内容等。除开最新修订版之外,咱们还能够在命令后面接上 “--revision 版本号”
来指定某一个修订版的显示。
另外,咱们还能够用以下命令来显示版本库的具体树形结构,后面的 “--show-ids”
选项指定显示每个显示元素的修改版本 ID。
$ svnlook tree /etc/svn/repos/ --show-ids / <0.0.r1/1007> project_test/ <1.0.r1/333> trunk/ <2.0.r1/0> branches/ <3.0.r1/74> tags/ <4.0.r1/152> project_luni/ <5.0.r1/793> trunk/ <6.0.r1/454> branches/ <7.0.r1/530> tags/ <8.0.r1/609>
这里有一个须要新手,尤为是习惯了 Subversion 客户端命令 “svn”
的用户注意的问题,那就是,“svnadmin”
和 “svnlook”
都被认为是服务器端的管理工具,只被用于版本库所在的机器,用来检查和维护版本库,不能经过网络来执行任务。因此,试图将 URL 甚至本地 file路径传递给这两个程序,都是错误的。
Subversion 还有不少管理工具可供管理员应用,须要了解这项工具的使用方法,读者们能够用 svn help
, svnadmin help
, svnlook help
等等命令查看帮助信息,另外,Subversion 参考手册提供了更为全面和详细的使用介绍。
Subversion 设计了一个抽象的网络层,版本库创建完毕以后,能够经过各类服务器向外公布。svnserve 是 Subversion 自带的一个小型的服务器,它使用独立的协议与客户端。咱们能够经过
svnserve –i
做为 inetd 启动或者
svnserve –d
做为守护进程启动一个服务。服务器启动后,客户端便可以经过绝对路径访问。如上例能够访问 svn://服务器IP/etc/svn/repos
。同时能够指定一些选项,经常使用的如 -r
,用来指定版本库的根路径,例如假设版本库位于 /etc/svn/repos:
svnserve –d -r /etc/svn
则客户端能够经过以下 URL 访问服务器:svn://服务器IP/repos
, 这样能够有效的避免暴露本地路径。另外如 --listen-port
,--listen-host
能够指定绑定的地址和端口,-R
能够强制设定为 Read-Only 模式。若是在 Windows 操做系统下,能够将版本库设定在 C 分区,如 c:\svnroot\repos
能够经过svn://服务器IP/svnroot/repos访问
,若是在其余分区,就必需要经过 -r
选项来指定 root 位置。
svnserve 能够经过配置 svnserve.conf 来进行一些简单的访问权限控制。你能够在版本库的 conf子文件夹下发现这个文件。文件的初始内容大体以下:
[general] # anon-access = read # auth-access = write password-db = passwd # authz-db = authz # realm = My First Repository
其中 anon-access
表示匿名用户的权限,auth-access
表示认证用户的权限设置,password-db
指向保存用户账号密码的文件的位置,可使用相对路径。svnserve 只能对全局提供简单的访问控制,若是想要更加灵活的方式,可使用 Apache Http Server 做为向外公布版本库的方式。
经过 Http 协议访问版本库是 Subversion 的亮点之一。使用 Http 协议意味着只须要打开浏览器,输入 URL 便可轻松的浏览整个版本库。灵活一般带来复杂性,Http 方式相对于 svnserve 方式来讲须要更多的配置。
因为 Subversion 须要版本化的控制,所以标准的 Http 协议不能知足需求。要让 Apache 与 Subversion 协同工做,须要使用 WebDAV(Web 分布式创做和版本控制)。WebDAV 是 HTTP 1.1 的扩展,关于 WebDAV 的规范和工做原理,能够参考 IETF RFC 2518。
为了使 Subversion 与 dav 模块通讯,须要安装 mod_dav_svn 插件,能够在 Subversion 的安装目录中找到。将其拷贝到 Apache 安装目录的 modules 文件夹下。接下来就是配置 Apache 的 httpd.conf 文件,让 Apache 在启动的时候加载上述模块。
须要添加的内容以下:
LoadModule dav_module modules/mod_dav.so LoadModule dav_svn_module modules/mod_dav_svn.so <Location /repos> DAV svn SVNPath /etc/svn/repos </Location>
首先须要启用 dav_module,而后加载 dav_svn_module。Location 标签指出访问的 URL 以及在服务器上的实际位置。配置完毕后从新启动 Apache,打开浏览器,输入 http://服务器IP/repos
将会看到以下画面:
这表示 Apache 的 dav_svn 模块已经能够正常工做了。用户可使用任何一种 Subversion 的客户端经过 Http 协议访问你的版本库。
若是想要指定多个版本库,能够用多个 Location 标签,也可使用 SVNParentPath 代替 SVNPath,例如在 /etc/svn
下有多个版本库 repos1,repos2 等等,用以下方式指定:
<Location /repos> DAV svn SVNParentPath /etc/svn </Location>
"SVNParentPath /etc/svn" 表示 /etc/svn 下的每一个子目录都是一个版本库。能够经过 http://服务器IP/repos/repos1
,http://服务器IP/repos/repos2
来访问。
如今你的版本库任何人均可以访问,而且有彻底的写操做权限。也就是说任何人均可以匿名读取,修改,提交,以及删除版本库中的内容。显然大部分场合这是不符合需求的。那么如何进行权限设置呢,Apache 提供了基本的权限设置:
首先须要建立一个用户文件。Apache 提供了一个工具 htpasswd,用于生成用户文件,能够在 Apache 的安装目录下找到。具体使用方法以下:
htpasswd etc/svn/passwordfile username
若是 passwordfile 不存在,能够加上 -c
选项让 htpasswd新建一个。建立好的文件内容是用户名加上密码的 MD5 密文。
接下来修改 httpd.conf,在 Location 标签中加入以下内容:
AuthType Basic AuthName "svn repos" AuthUserFile /etc/svn/passwordfile Require valid-user
从新启动 Apache, 打开浏览器访问版本库。Apache 会提示你输入用户名和密码来认证登录了,如今只有 passwordfile 文件中设定的用户才能够访问版本库。也能够配置只有特定用户能够访问,替换上述 "Require valid-user" 为 "Require user tony robert" 将只有 tony 和 robert 能够访问该版本库。
有的时候也许不须要这样严格的访问控制,例如大多数开源项目容许匿名的读取操做,而只有认证用户才容许写操做。为了实现更为细致的权限认证,可使用 Limit 和 LimitExcept 标签。例如:
<LimitExcept GET PROPFIND OPTIONS REPORT> require valid-user </LimitExcept>
如上配置将使匿名用户有读取权限,而限制只有 passwordfile 中配置的用户可使用写操做。若是这还不能知足你的要求,可使用 Apache 的 mod_authz_svn 模块对每一个目录进行认证操做。
首先须要让 Apache 将 mod_authz_svn 模块加载进来。在 Subversion 的安装目录中找到 mod_auth_svn 模块,将其拷贝到 Apache 安装目录的 modules 子目录下。修改 httpd.conf 文件,找到
LoadModule dav_svn_module modules/mod_dav_svn.so
在其后面加上
LoadModule authz_svn_module modules/mod_authz_svn.so
如今能够在 Location 标签中使用 authz 的功能了。一个基本的 authz 配置以下:
<Location /repos> DAV svn SVNPath /etc/svn/repos AuthType Basic AuthName "svn repos" AuthUserFile /etc/svn/passwd AuthzSVNAccessFile /etc/svn/accesspolicy Satisfy Any Require valid-user </Location>
AuthzSVNAccessFile 指向的是 authz 的策略文件,详细的权限控制能够在这个策略文件中指定,如:
#两个分组:committers,developers [groups] committers = paulex richard developers = jimmy michel spark sean \ steven tony robert #在根目录下指定全部的用户有读权限 [/] * = r #追加 committers 组用户有读写权限 @committers = rw #在 branches/dev 目录下指定 developers 组的用户有读写权限 [/branches/dev] @developers = rw #在 /tags 组下给予用户 tony 读写权限 [/tags] tony = rw #禁止全部用户访问 /private 目录 [/private] * = #给 committers 组用户读权限 @committers= r
使用 SVNParentPath 代替 SVNPath 来指定多个版本库的父目录时,其中全部的版本库都将按照这个策略文件配置。例如上例中 tony 将对全部版本库里的 /tags 目录具备读写权限。若是要对具体每一个版本库配置,用以下的语法:
[groups] project1_committers = paulex richard project2_committers = jimmy michel spark sean \ steven tony robert [repos1:/] * = r @ project1_committer = rw [repos2:/] * = r @ project2_committer = rw
这样项目1的 committer 组只能对 repos1 版本库下的文件具备写权限而不能修改版本库 repos2,一样项目2的 commiter 也不能修改 repos1 版本库的文件。
到目前为止咱们的用户名密码文件仍是以文本文件形式存放在文件系统中的,出于安全性的须要或者单点登录等可扩展性的考虑,文本文件的管理方式都不能知足需求了。经过 Apache 的 module_auth_mysql 模块,咱们能够用 MySQL 来保存用户信息。该模块的主页在 http://modauthmysql.sourceforge.net/,你也能够在 http://modules.apache.org/ 找到它的发行版本。安装方法同上述 Apache 的模块同样,拷贝至 modules 目录并在 httpd.conf 文件中添加以下语句:
LoadModule mysql_auth_module modules/mod_auth_mysql.so
相应的 Location 区域改写为:
<Location /repos> AuthName "MySQL auth" AuthType Basic AuthMySQLHost localhost AuthMySQLCryptedPasswords Off AuthMySQLUser root AuthMySQLDB svn AuthMySQLUserTable users require valid-user </Location>
而后在 mysql 中添加名为 svn 的数据库,并创建 users 数据表:
create database svn; use svn; CREATE TABLE users ( user_name CHAR(30) NOT NULL, user_passwd CHAR(20) NOT NULL, user_group CHAR(10), PRIMARY KEY (user_name) );
在 users 表中插入用户信息
insert into users values('username','password','group');
从新启动 Apache,在访问版本库的时候 Apache 就会用 mysql 数据表中的用户信息来验证了。
经过 Apache 的网络连接,版本库中的代码和数据能够在互联网上传输,为了不数据的明文传输,实现安全的版本控制,须要对数据的传输进行加密。Apache 提供了基于SSL 的数据传输加密模块 mod_ssl,有了它,用户就能够用 https 协议访问版本库,从而实现数据的加密传输了。SSL 协议及其实现方式,是一个很是复杂的话题,本文只是介绍 Apache 提供的最基本的SSL配置方法,更加详细的介绍内容,请参考 http://httpd.apache.org/docs-2.0/ssl/ 上的文档。
开始配置前,咱们须要一个实现 Apache 中 SSL 模块的动态程序库,一般名为 mod_ssl.so,及其配置文件,一般名为 ssl.conf。这个实现是跟 Apache 的版本相关的,不匹配的版本是不能用的;并且,并非每个 Apache 的版本都自带了相关实现文件,不少状况下,咱们须要本身去搜寻相关文件。另外,咱们还须要 OpenSSL 软件及其配置文件,来生成加密密钥和数字证书。这里,咱们可使用一些免费网站,如 http://hunter.campbus.com/ 上提供的集成版本的 Apache。
有了相关的工具和文件,咱们就能够开始生成 SSL 的证书和密钥了。首先,咱们须要找到 openssl 程序及其配置文件 openssl.cnf,运行以下命令来生成 128 位的 RSA 私有密钥文件
my-server.key: openssl genrsa -des3 -out my-server.key 1024 Loading 'screen' into random state - done Generating RSA private key, 1024 bit long modulus .....++++++ ........++++++ e is 65537 (0x10001) Enter pass phrase for server.key:******** Verifying - Enter pass phrase for server.key:********
命令运行期间须要用户输入并确认本身的密码。
如今,咱们须要 SSL 的认证证书,证书是由 CA(certificate authority) 发放而且认证的。为此,咱们能够用以下命令生成一个 CSR(Certificate Signing Request) 文件发给 CA,从而获得 CA 的认证:
openssl req -new -key my-server.key -out my-s erver.csr -config openssl.cnf
固然,通常状况下,若是 Subversion 的用户不是太多,安全状况不是很复杂,咱们也能够生成一个自签名的认证证书,从而省去了向 CA 申请认证的麻烦。以下命令:
openssl req -new -key my-server.key -x509 -out my-server.crt -config openssl.cnf
以上两个命令都须要用户输入那个 key 文件的密码,以及一些网络设置信息,如域名,邮箱等等,这里输入的服务器域名应该与 Apache 配置文件当中的一致。如今,咱们能够在 Apache 的 conf 目录下新建一个 ssl 目录,将 my-server.key 和 my-server.crt 文件都移动到 ssl 目录里面。而后修改 ssl.conf 文件,将 SSLCertificateKeyFile 和 SSLCertificateFile 项指向这两个文件。
若是 Apache 的 module 目录里面没有 mod_ssl.so 文件,能够将事先准备好的文件拷贝过去。而后,咱们能够设置 Apache 的配置文件 httpd.conf,将 ssl 模块加入其中:
LoadModule ssl_module modules/mod_ssl.so
而后,在配置文件的最后,加上以下 SSL 相关配置项:
SSLMutex default SSLRandomSeed startup builtin SSLSessionCache none ErrorLog logs/SSL.log LogLevel info <VirtualHost svntest.ut.cn.ibm.com:443> SSLEngine On SSLCertificateFile conf/ssl/my-server.crt SSLCertificateKeyFile conf/ssl/my-server.key </VirtualHost>
这样,基本的设置工做就完成了。从新启动 Apache 服务器,如今能够用 https 协议代替 http 协议来访问版本库了。若是要限定版本库只能用 https 访问,咱们能够在 Apache 配置文件当中 Subversion 部分加上 “SSLRequireSSL”。以下:
<Location /repos> DAV svn SVNPath /etc/svn/repos ………….#other items SSLRequireSSL </Location>
Subversion 以其优良的版本控制功能,灵活的网络访问模型,以及与 Apache 服务器联合配置所带来的更强大的管理控制功能,逐渐在开源软件开发的实践当中获得普遍的应用。本文重点介绍了 Subversion 服务器端的配置以及与 Apache 服务器联合配置的基本步骤和简单应用,实现了简单的实例应用。读者若是想要进一步了解相关信息,请参考文章后面列出的相关资料。