CENTOS 搭建SVN服务器(附自动部署到远程WEB)
安装subversion服务端
# 安装 yum install -y subversion # 测试是否安装成功 如果显示了版本信息则表示安装成功 svnserve --version;sleep 5s # svn配置建立svn版本库目录可建多个: PATHSSS="/home/svn" echo SVN仓库将创建在:$PATHSSS;sleep 5s # 新建一个版本库目录 mkdir -p $PATHSSS cd $PATHSSS # 建立svn版本库: svnadmin create $PATHSSS # 先设置passwd cat >$PATHSSS/conf/passwd<<ANGIE.K [users] jianglinzhi = jianglinzhi root1 = root ANGIE.K # 再设置权限authz cat >$PATHSSS/conf/authz<<ANGIE.K [groups] #用户组 admin = jianglinzhi,root1 coder = coders1,coders2,coders3 ui_and_ue = ui1,ui2,ui3 [/] #/仓库权限 @admin = rw @coder = rw @ui_and_ue = rw ANGIE.K # 最后设定svnserve.conf cat >$PATHSSS/conf/svnserve.conf<<ANGIE.K [general] # 使非授权用户无法访问 anon-access = none # 使授权用户有写权限 auth-access = write # 用户密码文件 password-db = passwd # 访问控制文件 authz-db = authz # 认证命名空间,subversion会在认证提示里显示,并且作为凭证缓存的关键字。 realm = 姜林志的第一个SNV服务器 欢迎你. ANGIE.K # 启动 默认端口 3690 killall svnserve svnserve -d -r $PATHSSS # 加入开机启动 echo svnserve -d -r $PATHSSS >> /etc/rc.local
配置和管理svn
1). 每个仓库的配置文件在$repos/conf/下,vi svnserve.conf,
配置项在[general]下:
anon-access:匿名用户的权限,可以为read,write和none,默认值read。不允许匿名用户访问:anon-access = none
auth-access:认证用户的权限,可以为read,write和none,默认值write。
password-db:密码数据库的路径,去掉前边的#
authz-db:认证规则库的路径,去掉前边的#。
注意:这些配置项的行都要顶格,否则会报错。修改配置后需要重启svn才能生效。
2). 配置passwd文件
这是每个用户的密码文件,比较简单,就是“用户名=密码”,采用的是明码。如allen=111111
3). 配置authz文件
1. [groups] section:为了便于管理,可以将一些用户放到一个组里边,比如:owner=allen,ellen
2. groups下边的sections表示对一个目录的认证规则,比如对根目录的认证规则的section为[/]。
设置单用户的认证规则时一个用户一行,如:
[/]
allen=rw #allen对根目录的权限为rw
ellen=r #ellen对根目录的权限为r
如果使用group,需要在group名字前加@,如
@owner=rw #group owner中的用户均为rw,等价于上边的两句话
启动时如果从/home/.svn/astar启动,/就是astar目录,用如上方式以astar目录为根设置权限。
如果从/home/.svn/启动,每个仓库根还是自己的起始目录。可以采用如上方式设置astar的权限,也可以采用如下方式:
[astar:/]
@owner=rw
设置test的权限如下:
[test:/]
@harry_and_sally = rw
简言之,每个仓库的根目录(/)就是自己的起始目录;[repos:/]这种方式只适用于多仓库的情况;[/]适合于单仓库和单仓库的方式。
3. 不能跨越仓库设置权限。
导入工程和第一次检出
导入到仓库
cd 进入工程目录上一级
执行:
#导入前先处理下WIN不支持的文件名 如 : * ? " < > | # find ./ -name "*\?*" #查找 # find ./ -name "*\?*" -print -exec rm -rf {} \; #删除 # find ./ -name "*\:*" -print -exec rm -rf {} \; #删除 # find ./ -name "*\"*" -print -exec rm -rf {} \; #删除 # find ./ -name "*\<*" -print -exec rm -rf {} \; #删除 # find ./ -name "*\>*" -print -exec rm -rf {} \; #删除 # find ./ -name "*\|*" -print -exec rm -rf {} \; #删除 提示:如果你设置了pre-commit钩子(比如:强制要求注释,请先解除这个钩子,以免导入失败) svn import 待导入工程路径(目录) svn://127.0.0.1/定义工程在仓库的目录名字 -m "对于本次操作的注释" 或者 切换到待导入目录 svn import ./ svn://127.0.0.1/定义工程在仓库的目录名字 -m "对于本次操作的注释"
将在仓库中新建工程目录和文件
检出到工程
cd 进入工程目录 执行即可
svn co svn://127.0.0.1 ./
判定程序员是否为补丁添加注释(per-commit)
这个钩子脚本,在每次commit之后会执行,格式是SHELL脚本,是从网上收集来的测试可用
这个文件的详细路径请看下面的cd命令
cd $PATHSSS/hooks cp per-commit.tmpl per-commit chmod 755 per-commit vi $PATHSSS/hooks/per-commit ############################################### #!/bin/sh # PRE-COMMIT HOOK # .... 中间省略 # http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ REPOS="$1" TXN="$2" SVNLOOK=/usr/bin/svnlook LOGMSG=`$SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" | wc -c` if [ "$LOGMSG" -lt 8 ];#要求注释不能少于8个字符,您可自定义 then echo -e "\n======================================================" 1>&2 echo -e "\n请在Commit(提交)前为您的补丁添加必要的注释。\n本次提交被忽略。" 1>&2 echo -e "\n======================================================" 1>&2 exit 1 fi
自动同步到WEB服务器(post-commit)
这个钩子脚本,在每次commit之后会执行,格式是SHELL脚本,是从网上收集来的测试可用
这个文件的详细路径请看下面的cd命令
# 配置自动发布到WEB服务器 编辑 post-commit 文件 cd $PATHSSS/hooks cp post-commit.tmpl post-commit chmod 755 post-commit vi $PATHSSS/hooks/post-commit ############################################### #!/bin/sh # ------------------------------------------------------------------------------- # Filename: post-commit # Description: WEB server with synchronization code by SVN # ------------------------------------------------------------------------------- #Version 1.0 #当用戶把代碼提交完成时,把代碼中的最新更改同步到 WEB服務器,同時注意不包括刪除操作。 #Set variable SVN=/home/svn SVNUSER=root1 SVNPASD=root WEB=/home/ftp/svn #待上传到WEB服务器的文件存放路径 第一次 需要先到该目录检出一次svn co svn://127.0.0.1 ./ WEBIP="192.168.0.23" RSYNC=rsync LOG=/home/svn/post-commit.log export LANG=en_US.UTF-8 mkdir -p $SVN mkdir -p $WEB #更新文件到本地文件夹 svn update $WEB --username $SVNUSER --password $SVNPASD #如果前面的代码成功完成,会继续执行下面的代码 if [ $? == 0 ] then echo "" >> $LOG echo `date` >> $LOG echo "##############################" >> $LOG chown -R nobody:nobody $WEB #同步代码从SVN服务器到WEB服务器 通过RSYNC $RSYNC -vaztpH --timeout=90 --exclude-from=$SVN/exclude.list $WEB root@$WEBIP:$WEB/ >> $LOG fi
完善后的另外一个版本
#!/bin/sh # POST-COMMIT HOOK # ... 省略 # http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ # mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf echo -e "[1 fo 6]================================\n`date`:这次更新将发布到测试和WEB。" 1>&2 # 库的路径 REPOS="$1" # 新提交的版本号 REV="$2" changed=$(svnlook changed -r $REV $REPOS) echo $changed > /home/svn/hooks/last_changed echo $REPOS >> /home/svn/hooks/last_changed echo $REV >> /home/svn/hooks/last_changed ###################################################################################### # 配置自动发布到WEB服务器 编辑 post-commit 文件 ###################################### ###################################################################################### # ------------------------------------------------------------------------------- # Filename: post-commit # Description: WEB server with synchronization code by SVN # ------------------------------------------------------------------------------- #Version 1.1 #当用戶把代碼提交完成时,把代碼中的最新更改同步到 WEB服務器,同時注意不包括刪除操作。 #Set variable SVN=/home/svn SVNUSER=root1 SVNPASD=root # 测试服务器路径 WEB1=/home/ftp/e/ecshop_2013/wwwroot WEB2=/home/ftp/c/customer/wwwroot # 远端服务器IP WEBIP="192.168.1.1" # 同步方式 RSYNC=rsync # 同步日志 LOG=/home/svn/post-commit.log # 避免乱码 export LANG=en_US.UTF-8 mkdir -p $SVN #更新文件到本地文件夹 svn update $WEB1 --username $SVNUSER --password $SVNPASD svn update $WEB2 --username $SVNUSER --password $SVNPASD # 必须要检出成功才开始执行下面的 ##################################################### if [ $? == 0 ] then echo -e "[2 fo 6]================================\n`date`:文件顺利检出到测试项目。" 1>&2 ###################################################################################### # 这里是解析本次操作的文件名 用于提高修改权限的速度 ################################## ###################################################################################### echo -e "[3 fo 6]================================\n`date`:正在改变文件归属,为上传到WEB服务器准备。" 1>&2 str=$changed # 字符串变成类似数组的东西,下面的for可以一次打印一个出来 var=`echo $str | awk -F',' '{print $0}' | sed "s/,/ /g"` # list为文件名和SVN标记码一次搞一个出来 for list in $var do # 获取每次list字符串的长度 filesneme_len=`expr length $list` # 这个if对长度小于1的文件名过滤掉>符号需要转义 if [ "$filesneme_len" \> "1" ] then # 这里取得的是字符串的第一个/前后的字符串 分别为仓库名字和带路径文件名 #echo 仓库:${list%%/*} #echo 文件:/${list#*/} # 根据仓库名字给文件分派权限 if [ "${list%%/*}" == "ec_qiuyi" ] then #设定检出文件为用户组1 echo 设定检出文件为用户组1 echo 仓库:${list%%/*} echo 文件:/${list#*/} chown 1000:1100 $WEB1/${list#*/} # 只同步修改的内容 rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB1/${list#*/}" "root@$WEBIP:$WEB1\_svn/${list#*/}" >> $LOG fi if [ "${list%%/*}" == "customer" ] then #设定检出文件为用户组2 echo 设定检出文件为用户组2 echo 仓库:${list%%/*} echo 文件:/${list#*/} chown 1002:1100 $WEB2/${list#*/} # 只同步修改的内容 rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB2/${list#*/}" "root@$WEBIP:$WEB2\_svn/${list#*/}" >> $LOG fi fi done echo -e "[4 fo 6]================================\n`date`:文件归属修改完成。" 1>&2 ###################################################################################### # 记录日志和上传文件 ################################################################# ###################################################################################### echo "" >> $LOG;echo `date` >> $LOG;echo "##############################" >> $LOG # 修改新检出文件的权限 # chown -R 1000:1100 $WEB # chown -R 1002:1100 $WEB2 #同步代码从SVN服务器到WEB服务器 通过RSYNC #$RSYNC -vaztpH --timeout=90 --exclude-from=$SVN/exclude.list $WEB root@$WEBIP:$WEB/ >> $LOG echo -e "[5 fo 6]================================\n`date`:正上传到WEB服务器,并检查文件完整。" 1>&2 # 同步完整内容 如目录删除文件删除之类.. rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB1/" "root@$WEBIP:$WEB1\_svn/" >> $LOG rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB2/" "root@$WEBIP:$WEB2\_svn/" >> $LOG echo -e "[6 fo 6]================================\n`date`:代码已经发布到远端WEB。" 1>&2 fi # 利用钩子错误退出 输出过程信息 exit 1
完善后的另外二个版本
#!/bin/sh ###################################################################################### # 配置自动发布到WEB服务器 编辑 post-commit 文件 ###################################### ###################################################################################### # ------------------------------------------------------------------------------- # Filename: post-commit # Description: WEB server with synchronization code by SVN # ------------------------------------------------------------------------------- #Version 1.0 #当用戶把代碼提交完成时,把代碼中的最新更改同步到 WEB服務器,同時注意不包括刪除操作。 echo -e "[1 fo 6]================================\n`date`:这次更新将发布到测试和WEB。" 1>&2 # 库的路径 REPOS="$1" # 新提交的版本号 REV="$2" changed=$(svnlook changed -r $REV $REPOS) echo $changed > /home/svn/hooks/last_changed echo $REPOS >> /home/svn/hooks/last_changed echo $REV >> /home/svn/hooks/last_changed #Set variable SVN=/home/svn SVNUSER=本地管理员ID SVNPASD=本地管理员密码 mkdir -p $SVN # 测试服务器路径 WEB1=/home/ftp/e/ecshop_2013/wwwroot WEB2=/home/ftp/c/customer/wwwroot WEB3=/home/ftp/u/ugg_ecshop_2013/wwwroot WEB4=/home/ftp/l/luck_ecshop_2013/wwwroot # 同步标记 WEB1_SYNC=NO WEB2_SYNC=NO WEB3_SYNC=NO WEB4_SYNC=NO # 待同步操作数 WEB1_SYNC_NUM=0 WEB2_SYNC_NUM=0 WEB3_SYNC_NUM=0 WEB4_SYNC_NUM=0 # 同步方式 RSYNC=rsync # 同步日志 LOG=/home/svn/post-commit.log echo "================================================" > $LOG echo `date`:这是最近一次SVN提交的信息。>> $LOG echo "================================================" >> $LOG mkdir -p $WEB1 mkdir -p $WEB2 mkdir -p $WEB3 mkdir -p $WEB4 # 第一次需要检出 # svn co svn://127.0.0.1/ec_ugg ./ # 远端服务器IP WEBIP_QY="192.168.1.1" WEBIP_UG="192.168.1.2" WEBIP_LU="192.168.1.3" # 避免乱码 export LANG=en_US.UTF-8 #更新文件到本地文件夹 echo "================================================" >> $LOG echo "更新文件到本地文件夹" >> $LOG svn update $WEB1 --username $SVNUSER --password $SVNPASD >> $LOG svn update $WEB2 --username $SVNUSER --password $SVNPASD >> $LOG svn update $WEB3 --username $SVNUSER --password $SVNPASD >> $LOG svn update $WEB4 --username $SVNUSER --password $SVNPASD >> $LOG echo "================================================" >> $LOG # 必须要检出成功才开始执行下面的 ##################################################### if [ $? != 0 ] ; then echo -e "项目检出失败,同步终止!" 1>&2 exit $? fi echo -e "[2 fo 6]================================\n`date`:文件顺利检出到测试项目。" 1>&2 ###################################################################################### # 这里是解析本次操作的文件名 用于提高修改权限的速度 ################################## ###################################################################################### echo -e "[3 fo 6]================================\n`date`:正在改变文件归属,为上传到WEB服务器准备。" 1>&2 str=$changed # 字符串变成类似数组的东西,下面的for可以一次打印一个出来 var=`echo $str | awk -F',' '{print $0}' | sed "s/,/ /g"` # list为文件名和SVN标记码一次搞一个出来 for list in $var do # 获取每次list字符串的长度 filesneme_len=`expr length $list` # 这个if对长度小于1的文件名过滤掉>符号需要转义 if [ "$filesneme_len" \> "1" ] then # 这里取得的是字符串的第一个/前后的字符串 分别为仓库名字和带路径文件名 #echo 仓库:${list%%/*} #echo 文件:/${list#*/} # 根据仓库名字给文件分派权限 # 项目0 if [ "${list%%/*}" == "ec_qiuyi" ] then # 设定同步标记 WEB1_SYNC="YES" # 累加标记 WEB1_SYNC_NUM=$[$WEB1_SYNC_NUM+1] #设定检出文件为用户组1 echo 设定检出文件为用户组1 echo 仓库:${list%%/*} echo 文件:/${list#*/} chown 1000:1100 $WEB1/${list#*/} # 只同步修改的内容 #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB1/${list#*/}" "root@$WEBIP_QY:$WEB1\_svn/${list#*/}" >> $LOG # 同步完整内容 如目录删除文件删除之类.. #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB1/" "root@$WEBIP_QY:$WEB1\_svn/" >> $LOG # 项目0 fi # 项目1 if [ "${list%%/*}" == "customer" ] then # 设定同步标记 WEB2_SYNC="YES" # 累加标记 WEB2_SYNC_NUM=$[$WEB1_SYNC_NUM+1] #设定检出文件为用户组2 echo 设定检出文件为用户组2 echo 仓库:${list%%/*} echo 文件:/${list#*/} chown 1002:1100 $WEB2/${list#*/} # 只同步修改的内容 #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB2/${list#*/}" "root@$WEBIP_QY:$WEB2\_svn/${list#*/}" >> $LOG # 同步完整内容 如目录删除文件删除之类.. #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB2/" "root@$WEBIP_QY:$WEB2\_svn/" >> $LOG # 项目1 fi # 项目2 if [ "${list%%/*}" == "ec_ugg" ] then # 设定同步标记 WEB3_SYNC="YES" # 累加标记 WEB3_SYNC_NUM=$[$WEB1_SYNC_NUM+1] #设定检出文件为用户组3 echo 设定检出文件为用户组3 echo 仓库:${list%%/*} echo 文件:/${list#*/} chown 1000:1100 $WEB3/${list#*/} # 只同步修改的内容 #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB3/${list#*/}" "root@$WEBIP_UG:$WEB3\_svn/${list#*/}" >> $LOG # 同步完整内容 如目录删除文件删除之类.. #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB3/" "root@$WEBIP_UG:$WEB3\_svn/" >> $LOG # 项目2 fi # 项目3 if [ "${list%%/*}" == "ec_luck" ] then # 设定同步标记 WEB4_SYNC="YES" # 累加标记 WEB4_SYNC_NUM=$[$WEB1_SYNC_NUM+1] #设定检出文件为用户组4 echo 设定检出文件为用户组4 echo 仓库:${list%%/*} echo 文件:/${list#*/} chown 1000:1100 $WEB4/${list#*/} # 只同步修改的内容 #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB4/${list#*/}" "root@$WEBIP_LU:$WEB1\_svn/${list#*/}" >> $LOG # 同步完整内容 如目录删除文件删除之类.. #rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB4/" "root@$WEBIP_LU:$WEB1\_svn/" >> $LOG # 项目3 fi fi done echo -e "[4 fo 6]================================\n`date`:文件归属修改完成。" 1>&2 ###################################################################################### # 记录日志和上传文件 ################################################################# ###################################################################################### echo "" >> $LOG;echo `date` >> $LOG;echo "##############################" >> $LOG # 修改新检出文件的权限 # chown -R 1000:1100 $WEB # chown -R 1002:1100 $WEB2 #同步代码从SVN服务器到WEB服务器 通过RSYNC #$RSYNC -vaztpH --timeout=90 --exclude-from=$SVN/exclude.list $WEB root@$WEBIP:$WEB/ >> $LOG echo -e "[5 fo 6]================================\n`date`:正上传到WEB服务器,并检查文件完整。" 1>&2 # 同步完整内容 如目录删除文件删除之类.. echo "================================================" >> $LOG echo "同步完整内容 如目录删除文件删除之类.." >> $LOG if [ "$WEB1_SYNC" == "YES" ] then echo -e "正同步($WEB1_SYNC_NUM个操作记录)到 球衣服务器" 1>&2 time rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB1/" "root@$WEBIP_QY:$WEB1\_svn/" >> $LOG # 球衣 fi if [ "$WEB2_SYNC" == "YES" ] then echo -e "正同步($WEB2_SYNC_NUM个操作记录)到 客服系统服务器" 1>&2 time rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB2/" "root@$WEBIP_QY:$WEB2\_svn/" >> $LOG # 客服系统 fi if [ "$WEB3_SYNC" == "YES" ] then echo -e "正同步($WEB3_SYNC_NUM个操作记录)到 UGG孩子服务器" 1>&2 time rsync -vzurtopg --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB3/" "root@$WEBIP_UG:$WEB3\_svn/" >> $LOG # UGG鞋子 fi if [ "$WEB4_SYNC" == "YES" ] then echo -e "正同步($WEB4_SYNC_NUM个操作记录)到 吉祥符服务器" 1>&2 time rsync -vzurtopg '-e ssh -p 10079' --delete --timeout=60 --exclude-from=$SVN/exclude.list "$WEB4/" "root@$WEBIP_LU:$WEB1\_svn/" >> $LOG # 吉祥符 fi echo -e "[6 fo 6]================================\n`date`:代码已经发布到远端WEB。" 1>&2 echo "================================================" >> $LOG # 利用钩子错误退出 输出过程信息 exit 1
一个强制要求程序员为自己的上传注释的钩子(pre-commit)
REPOS="$1" TXN="$2" # Make sure that the log message contains some text. SVNLOOK=/usr/bin/svnlook # $SVNLOOK log -t "$TXN" "$REPOS" | \ # grep "[a-zA-Z0-9]" > /dev/null || exit 1 LOGMSG=`$SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" | wc -c` if [ "$LOGMSG" -lt 8 ];#要求注释不能少于8个字符,您可自定义 then echo -e "\n======================================================" 1>&2 echo -e "\n请在Commit(提交)前为您的补丁添加必要的注释。\n本次提交被忽略。" 1>&2 echo -e "\n======================================================" 1>&2 exit 1 fi # 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