SVN的搭建、使用与维护

SVN教程目录

SVN与Git各自的优缺点

只是日常简单使用,不参与维护的同学可以直接前往轻松上手一节。


搭建与维护

新开的云服务器实例记得先设好防火墙(也就是安全组)再搞别的,安全第一。阿里云默认ssh端口允许所有ip访问,为了服务器少挨打,目前只对已知可靠的ip也就是我们内部人员开放。

部署方面,阿里云的教程已经讲得很清楚了,直接看它的就可以了。镜像用的是Alibaba Cloud Linux 3.2104 64位

# 启动SVN服务,根目录是/data/svn,这里是所有项目仓库的上层目录
svnserve -d -r /data/svn/
# 停止SVN服务(也可以lsof -i:3690然后kill对应的进程)
killall svnserve

多个项目共享的配置文件放在/data/svn

创建新项目:svnadmin create /data/svn/project_name,新项目的conf/svnserve.conf和整个hooks/目录一般直接从旧项目拷贝过来就可以了,conf/authz, conf/passwdconf/hooks-env删掉以免造成混淆,然后在/data/svn/authz中设置这个项目的权限,之后就可以进行checkoutcommit了。

SVN多项目管理
authz文件中,[/foo/bar]用于单项目的情况,此时根目录就是项目目录;[repository:/baz/fuz]用于多项目且配置文件共享的情况,此时根目录是项目的上级目录,配置文件也都放在这个目录下。由于设置子目录权限必须先设置子目录上级的权限,因此根目录必须给予足够的权限,否则下面的各个仓库不管权限如何都会出现authorization failed。下面是一个示例,demo用户对两个项目都有读写权限:

[/]
demo = rw

[svnrepos:/]
demo = rw

[maintenance:/]
demo = rw

重置/修改登录用户名:如果我们在最开始的时候使用测试的用户名密码(也有可能是前同事的账号密码),后续使用自己的用户名密码,会发现tortoiseSVN记住了第一次的用户名密码,导致登录不上去,这时需要重置用户名,方法见下图:

重置之后重新updatecommit,就会提示输入新的账号密码,问题就解决了。参考链接

SVN更换远程仓库地址,项目早期可能会出现更改项目仓库名称的情况,这是svn仓库的url就会更改,客户端就找不到仓库了,需要修改远程仓库地址:右键项目的根目录——TortoiseSVN——Relocate,参考链接



配置钩子

先放参考链接:钩子是一种在用户某些行为环节(commit, lock, revprop)前后触发操作的机制,最常见的是在commit前检查log,在commit后同步代码。
钩子们位于项目目录的hooks/目录下,文件后缀都是以.tmpl结尾,不起作用,只是作为模板给用户看,如果想要启用它们,只需将其.tmpl后缀去掉。
钩子们的环境变量配置在conf/hooks-env.tmpl里头,同样也是去掉后缀才生效。经测试,不使用配置文件,钩子照样可以正常运行。
目前的pre-commit钩子包含了两个功能,一个是提交时message不可以为空,一个是单文件大小不能超过200MB,具体写法如下:

# 添加对中文的支持,否则虽然svnlook changed命令可以正常工作,但svnlook cat等命令会找不到文件报file not exist错误,参考链接:https://blog.csdn.net/xixiaoxie2/article/details/53925043
export LANG=zh_CN.UTF-8

REPOS="$1"
TXN="$2"

# 要求提交时log message不能为空
SVNLOOK=/usr/bin/svnlook
msg=`$SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]"`
if [ -z "$msg" ];then
    # 将信息输出到标准错误流,同时exit非零,这样才会在svn客户端中显示
    echo "提交时message不能为空!">&2
    # exit 非零就是不给提交
    exit 1
fi

# 要求单个文件不能超过200MB,一般这么大的文件都是ppt
# awk -F " "表示以空格为分隔符,NF是split出的段数,for循环的含义是打印从第2段到最后一段
# svnlook changed会得到形如"A test abc edf.jpg"的字符串,经过这个处理后变成"test abc edf.jpg",也就是得到了文件名
MAX_MB=200
MAX_SIZE=`expr $MAX_MB \* 1024 \* 1024`
files=`$SVNLOOK changed -t "$TXN" "$REPOS" | awk -F " " '{for (i=2;i<=NF;i++)printf("%s ", $i);print ""}'`
while read f; do
    # svnlook filesize 可以看某个仓库下某个文件的大小
    # 如果不加双引号,文件名中如果有空格就会被当成多个参数,引发错误
    filesize=`$SVNLOOK filesize -t "$TXN" "$REPOS" "$f"`
    if [[ $filesize -gt $MAX_SIZE ]] ; then
        echo "$f文件过大,不应超过$MAX_MB MB!">&2;
        exit 1
    fi
# 这个写法就是把变量files送进while read逐行拆开进行处理的意思
done <<< $files

# 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

# 通过所有检查就返回0,允许提交
exit 0

自动化更新服务器代码的脚本暂不考虑,详见参考链接



添加http支持

选用的方案是使用apache提供web服务,使用IF.SVNAdmin生成用户和仓库管理界面的GUI。

Apache是一个服务器软件,我们安装好apache并启动httpd服务,开放80端口之后,从外面访问http://ip/xxx就会有相应的回应。/var/www/html是其默认的根目录,如果我们在/var/www/html下创建/svnadmin目录,从外部通过http://ip/svnadmin就可以访问到了,参考链接

# 安装apache
yum install httpd -y
# 安装mod_dav_svn,它是apache服务器访问svn的一个模块
yum install mod_dav_svn -y

然后配置SVN的http访问配置文件/etc/httpd/conf.modules.d/10-subversion.conf,这个文件中加载了mod_svn模块(参考链接):

# 前面三行是自带的,后面的Location根据自己的需求加
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so
LoadModule dontdothat_module  modules/mod_dontdothat.so

# 下面是一个仓库页面配置的示例
# Location里的内容表示路径,服务启动后这个仓库的url就是http://ip/repo1
<Location /svn>
    DAV svn
    # 使用SVNParentPath参数指定的是仓库的上级目录,配置文件都放在上级目录,用于多项目共享配置的情况
    SVNParentPath /data/svn
    # 使用SVNPath参数指定的是仓库本级的目录,配置文件放在该仓库下面,用于每个项目使用各自配置的情况
    # SVNParentPath与SVNPath只需开启一个
    # SVNPath /data/svn/repo1
    # 认证方式是基本认证,也就是用户名+密码
    AuthType Basic
    # 为认证域所选定一个名字, 大多数浏览器会在提示用户输入用户名与密码的对话框上显示这个名字
    AuthName '/data/svn'
    # 用户和密码认证文件的位置
    AuthUserFile /data/svn/passwd_http
    # 用户权限文件的位置
    AuthzSVNAccessFile /data/svn/authz
    # 指定只有输入了正确的用户名和密码的用户可以访问URL,不能匿名访问
    Require valid-user
</Location>

如果使用SVNParentPath,那么10-subversion.conf里只需写一个location作为各项目的上级目录,各项目的权限都在同一个authz文件里头改,[/]代表各项目的上级目录,各项目的url是http://ip/svn/repo_name(上面示例代码的location标签给的是/svn路径);如果使用SVNPath,各项目的权限也是在authz文件里头改,[/]代表项目目录,url是http://ip/repo_name。每开一个新项目都要去10-subversion.conf里新增一个location,相对比较繁琐。

暂时没有找到能直接浏览所有项目列表的写法,TortoiseSVN跟httpd都没找到。

需要注意的是,权限文件svn访问跟http访问使用同一个权限文件就可以了,但是密码文件没法共用,因为svn访问的密码文件是明文密码,http访问用的是经过OpenSSL加密后的字符串,只能分开成两个文件。两个密码如何保持一同更新,暂时不知道怎么实现

接下来生成http访问要用的密码文件,也就是上面配置里头的passwd_http

# -b指使用命令行中的密码而不是提示输入密码
cd 项目目录/conf
htpasswd -b passwd_http username password
# 如果事先没有密码文件,-b会失败,要加上-c参数,但是-c会直接覆盖已有的文件,所以如果手残配置文件就没了,建议用touch而不是-c来创建密码文件,然后添加密码只用-b,防止翻车
htpasswd -bc passwd_http username password

最后重启一下服务:systemctl restart httpd,到这里就可以通过http://ip/svn/repo1访问repo1这个仓库了,SVN的http访问就完成了。每次修改10-subversion.conf都需要重启httpd服务才能应用更改。

此时SVN的后台维护依然是靠敲命令行,用户权限管理,仓库权限管理啥的都是,这样其实不太方便,IF.SVNAdmin给出了一个GUI,允许用户在web页面上管理SVN用户和用户组以及进行权限分配。

安装IF.SVNAdmin

# iF.SVNAdmin是用php写的,因此我们需要安装php
yum install php -y
wget http://sourceforge.net/projects/ifsvnadmin/files/svnadmin-1.6.2.zip/download -O svnadmin-1.6.2.zip
unzip svnadmin-1.6.2.zip
mkdir -p /var/www/html
# /var/www/html是apache默认的根目录里,因此下面三行的路径开头都必须是/var/www/html,否则后面的环节会访问不到这个页面
mv iF.SVNAdmin-stable-1.6.2/ /var/www/html/svnadmin
chown -R apache.apache /var/www/html/svnadmin
chmod -R 777 /var/www/html/svnadmin/data

如果前面apache已经配置完成,到这里就可以通过http:/ip/svnadmin进入GUI了。第一次进入这个页面时,会提示给出一些配置文件的路径,下图是一种可行的配置方式:

注意passwd文件要用htpasswd生成出来的文件,而不是那个明文文件,否则配置的时候不会报错,但是登录的时候就会一直提示密码错误。选完一个路径点一下右边的test,如果是"passed"就说明文件可以正常访问,否则可能会得不到预期的结果。

配置结束后会在/var/www/html/svnadmin/data目录下生成config.iniuserroleassignments.ini文件,它们分别保存刚才的配置信息与用户角色分配情况(管理员、普通用户等)。第一次配置的时候如果不小心没改好导致登不进后台,可以直接把这两个文件删了,重新访问页面重新配置,别把默认模板config.tpl.ini给删了就行。

userroleassignments.ini文件中可以看到当前的权限分配情况:

# 等号后面没有东西是正常的,[]里是用户名,Administrator=就是管理员账户,User=就是用户账户。
[admin]
Administrator=

[demo]
User=

需要注意的是iF.SVNAdmin无法显示中文目录,目前还没有找到解决的办法。



定时备份

SVN跟Git的一个区别在于,Git pull之后本地保存了所有版本的记录,可以在离线的情况下checkout到任意的版本,但是SVN update之后本地只有当前一个版本,它的checkout一定要在线,所以如果服务器崩了或者数据被误删了,记录就没了。接下来做一下SVN仓库的定时备份。

SVN有自带的同步命令svnsync,但是我一直没跑通,就放弃了,转用通用的文件同步工具rsync。rsync在windows下通过cwrsync实现,下载地址。安装后把cwRsync目录的绝对路径/bin加入Path环境变量,就可以使用rsync命令了,跟Linux上rsync的用法是一致的。

rsync使用方法

windows下使用rsync如果目标位置带盘符会被当做远程地址(因为Linux系统的地址是不会有:符号的),所以不要写绝对路径,用相对路径就可以了

rsync是借助ssh实现的,而ssh命令默认每次都要手动输入密码,不利于自动化,目前看到有两种解决方案,一种是通过expect撰写自动输入密码脚本
一种是通过密钥登录,我们选择了后者,因为操作方便,且运行的时候不容易出错:

# 一路回车生成id_rsa私钥和id_rsa.pub公钥,在服务器或本地都可以做此操作
ssh-keygen -t rsa

再把公钥id_rsa.pub放到服务器的~/.ssh/authorized_keys文件,把私钥id_rsa放在本地的~/.ssh/目录下,就可以实现ssh免密码登录了。尝试在一台电脑上配置多个ssh_key,没有成功,先不管它,暂时还用不到

windows下使用rsync会提示"Could not create directory ‘/home/username/.ssh’",导致每次都要问是否接受这个密钥,我们只要给它配个HOME环境变量,成功登录一次就解决了,参考链接

windows下使用常用的rsync -avzP src dst会出现"chown xxx failed: Invalid argument (22)"报错,因为windows的所有者、权限跟组的配置都跟Linux不一样,所以应当去掉-opg三个参数,参考链接

rsync故障排除解答

最后同步的命令为:rsync -rltDvzP --delete root@ip:/data/svn svn_backup/

(待更新)windows定时任务设置部分还没做,因为rsync突然出了点问题,总是提示“Enter passphrase for key ‘/cygdrive/c/Users/MSI/.ssh/id_rsa’:”,之前都已经可以免密直接下载了,后面再研究。



轻松上手

对于只是要下载SVN上某个文档的同学:

在浏览器访问http://ip/svn/仓库名,输入账号密码后进行浏览,找到所需的文件后直接单击它下载即可,详见下图:

也可以使用TortoiseSVN浏览和下载文件,使用SVN之前确保自己的账号已经注册好,如果没有注册请联系管理员拿到账号跟密码。同时安装好TortoiseSVN(附下载链接)。TortoiseSVN下载文件的操作见下图:

对于需要修改、上传文件的同学:

  1. 第一次使用需要进行checkout(检出),详见下图:

    SVN服务器的ip(图中的120.77.70.46仅用于测试)改成管理员提供的ip,使用自己的账号密码就可以成功checkout了(小贴士:checkout并不一定要把整个项目拉下来,可以只拉自己需要的那个下级目录,上传也只会上传到那个目录,这样可以大幅减少checkout在下载上花的时间)。

  2. 在对文件进行修改之前建议进行一次update(更新),以防近期有其他人提交了新的改动,详见下图:

  3. 完成对文件的修改之后进行一次commit(提交),把文件上传回服务器,提交时最好在message一栏写上这个提交做了什么事情,详见下图:

  4. 在项目目录(文件夹)下右键菜单,“TortoiseSVN”–"Show log"可以看到历次提交的日志信息。

  5. 开始编辑文档之前记得先update一下,把服务器上最新的版本拉下来再开始做修改。

  6. 由于阿里云的带宽很贵,我们配置的带宽有限,如果只是为了下载单个文件,建议像下图那样先通过TortoiseSVN的Repo-browser或者直接访问http页面确定文件位置或直接双击下载单个文件,而不是直接checkout整个项目仓库,那样可能要等待相当长的时间。

  7. 进入http://ip/svnadmin并登录可以修改自己账户http访问所用的密码,要修改TortoiseSVN的密码还是得找管理员。



进阶操作

  • 查看文件更改,比较文件:

    注意要选中某个文件才会有diff选项。有多种比较方式,有需要的再自行挖掘。

  • 在SVN中,两个人分别新增一个不同的文件并提交是可以成功的,假设原本版本号为4,甲新增file1并提交,服务器版本号为5;乙在4的基础上新增file2并提交,可以提交成功,服务器版本号为6;但在Git中,乙是不可以提交的。

  • 处理提交时冲突 :如果两个人同时在本地各自修改文件然后各自上传,后上传的人就会遇到冲突:

    按照下图所示,先把SVN服务器上的内容更新到本地,然后手动解决冲突,最后重新提交回服务器就可以了。

  • 版本回滚:方法一,Update to Revision,详见下图:

    HEAD就是当前最新的一个提交,输入版本号数字可以指定某个旧版本。这种做法与Git的checkout类似,把本地的代码刷新成了旧版本,
    如果此时修改代码并commit,会触发冲突,无法上传,因为这相当于从某个旧版本发起了一次commit,而SVN服务器上是更新的版本。
    所以这个方法一般只是为了查看历史版本。

    方法二,Revert to this version,详见下图:

    这个方法保持版本号不变,将文件内容修改为旧版本的,因此可以直接提交以覆盖掉最近的可能有问题的版本,与Git的`revert`类似。

    方法三,Revert changes from this version,略

    三种版本回滚方法的对比

  • Windows使用svn命令行:在这里下载Apache Subversion command line tools,解压后把里面的bin目录的路径添加到环境变量的Path中,就可以在cmd中使用svn命令了。参考链接


疑难杂症

  • commit时显示authorization failed

可能是密码错误,也可能是权限不够,如果在一个空文件夹中checkout同一个仓库没有问题,那就是权限不够,否则两种情况都有可能,实在搞不定就联系管理员

  • commit时显示commit failed:提交时产生冲突,详见处理提交时冲突

  • show log失败,报错Item is not readable:在svnserve.conf中,设置anon-access = none即可,参考链接

  • 搭建好之后在本地checkout失败:URL svn://xx.xx.xx.xx/svntest doesn’t exist
    原因:svn服务启动时选择的目录不对,启动服务的时候要选择svn的各种库的上级目录(比如/home/svn),而不是某个库的目录(比如/home/svn/svntest),参考链接

  • 待解决:有没有什么手段可以让用户浏览所有项目的列表?TortoiseSVN跟httpd都没找到这种方法。当然也可以先上iF.SVNAdmin上浏览仓库列表,不过这样就多了一步,麻烦。




其他链接

部署并使用Docker(Alibaba Cloud Linux 2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值