CENTOS 搭建SVN服务器(附自动部署到远程WEB)

时间:2021-06-01 16:37:38

安装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 # 启动 默认端口
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 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个字符,您可自定义
then
echo -e "\n======================================================" >&
echo -e "\n请在Commit(提交)前为您的补丁添加必要的注释。\n本次提交被忽略。" >&
echo -e "\n======================================================" >&
exit
fi

自动同步到WEB服务器(post-commit)

这个钩子脚本,在每次commit之后会执行,格式是SHELL脚本,是从网上收集来的测试可用
这个文件的详细路径请看下面的cd命令

# 配置自动发布到WEB服务器 编辑 post-commit 文件
cd $PATHSSS/hooks
cp post-commit.tmpl post-commit
chmod 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- mkdir -p $SVN
mkdir -p $WEB #更新文件到本地文件夹
svn update $WEB --username $SVNUSER --password $SVNPASD
#如果前面的代码成功完成,会继续执行下面的代码
if [ $? == ]
then
echo "" >> $LOG
echo `date` >> $LOG
echo "##############################" >> $LOG
chown -R nobody:nobody $WEB
#同步代码从SVN服务器到WEB服务器 通过RSYNC
$RSYNC -vaztpH --timeout= --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