svn
buyfakett
svn
目录结构
.
├── admin
│ ├── authz
│ └── passwd
└── data
启动
启动脚本
#!/bin/bash
docker stop svn
docker rm svn
docker run -d --name svn \
--restart=always \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
-v $(pwd)/data/:/data/svn/repos \
-v $(pwd)/admin/:/data/svn/reposadmin \
-v /data/test:/data/test \
-p 3690:3690 \
registry.cn-hangzhou.aliyuncs.com/buyfakett/svn
创建代码仓库
#版本控制管理工具
yum install subversion -y
#创建仓库
svnadmin create /data/app/svn/data/salt
配置权限和账户
#创建库
svnadmin create /data/svn/data/test
#修改权限
vi conf/authz
[salt:/]
test = rw
#修改密码
vi conf/passwd
[users]
test = test
#修改配置(password-db和authz-db可以写在一个地方,然后所有库都指向一个配置文件)
vi conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
注意!!!
svnserve.conf
中的anon-access
如果是read
,可能会导致提交没有commit信息和提交时间,需要改成none
修改hooks中的配置
#进入到钩子配置目录
cd /data/svn/repos/salt/hooks/
#拷贝一个提交后执行的文件
cp post-commit.tmpl post-commit
chmod 644 post-commit
修改post-commit中的配置
执行一次checkout svn co svn://127.0.0.1/whd ./ --username whd --password 123456
我拉取的路径在/data/test/whd/whd 修改 post-commit内容
#!/bin/sh
export LANG="zh_CN.UTF-8"
svn up /data/test/whd/whd --quiet --username whd --password 123456 >> /data/logs/svn/salt.log
备份和恢复
脚本
DETAILS
#!/bin/bash
###########
# svn 备份
###########
declare -A repos
repos=(
[test]=0
)
# 安装工具
function check_svn_tools() {
rpm -q subversion || yum install -y subversion > /dev/null 2>&1
mkdir -p ~/.subversion/
cat << EOF > /root/.subversion/servers
[groups]
store-plaintext-passwords = yes
[global]
store-passwords = yes
store-plaintext-passwords = yes
EOF
cat << EOF > ~/.subversion/config
[auth]
store-passwords = no
[helpers]
[tunnels]
[miscellany]
[auto-props]
EOF
}
# 同步文件
function sync_file() {
cmd_status=1
run_times=0
while [ ${cmd_status} != 0 ] && [ ${run_times} -le 3 ]; do # 连续失败 3 次
run_times=$((${run_times} + 1))
cp -rfv $1 $2
cmd_status=$?
done
if [ ${cmd_status} -eq 0 ];then
rm -rf $1
else
echo "同步失败三次, 源文件:$1, 目的文件:$2"
fi
}
function main() {
# 工具检查及配置
check_svn_tools
# 创建工作目录
rm -rf ${cache_dir} && mkdir -p ${cache_dir}
for repo in ${!repos[@]};do # 一次性获取最新版本号
revision=$(svn info --username ${svn_user} --password ${svn_password} ${svn_url}/${repo} | grep Revision | awk '{print $2}')
if [ "${revision}"x == ""x ]; then
revision=$(svn info --username ${svn_user} --password ${svn_password} ${svn_url}/${repo} | grep 最后修改的版本 | awk '{print $2}')
fi
repos[${repo}]=${revision}
done
for repo in ${!repos[@]};do # 开始循环所有仓库
# 最新版本号
revision=${repos[${repo}]}
# 备份起始版本号
start_version=0
end_version=0
for end_version in $(seq 0 ${revision});do # 开始循环版本号备份
if [ $((${end_version} - ${start_version} + 1)) -eq ${interval} ] || [ ${end_version} -eq ${revision} ];then # 批量备份
echo "开始备份 ${repo} 的 ${start_version} 至 ${end_version} 版本到 ${bakdir}/${repo}/${repo}_${start_version}_${end_version}.dump.gz, 共 ${revision}"
if [ -f ${bakdir}/${repo}/${repo}_${start_version}_${end_version}.dump.gz ];then # 判断当前文件是否已经备份
echo "跳过 ${repo} 的 ${start_version} 至 ${end_version} 版本"
start_version=$((${end_version} + 1))
continue
fi
# 备份当前版本号生成 dump 文件并 gzip 压缩后移动到备份目录
svnrdump dump --username "${svn_user}" --password "${svn_password}" ${svn_url}/${repo} -r ${start_version}:${end_version} --incremental | gzip > ${cache_dir}/${repo}_${start_version}_${end_version}.dump.gz && \
(test -d ${bakdir}/${repo} || mkdir -p ${bakdir}/${repo}) && \
sync_file ${cache_dir}/${repo}_${start_version}_${end_version}.dump.gz ${bakdir}/${repo}/
start_version=$((${end_version} + 1))
fi
end_version=$((${end_version} + 1))
done
done
}
# 从备份恢复数据
function restore() {
gunzip -c ${bakdir}/${repo}/${repo}_${version}.dump.gz | svnadmin load ${repos_dir}/${repo}
}
# svn 地址
svn_url="svn://172.168.1.58"
# svn 账号
svn_user="test"
# svn 密码
svn_password="test"
# 备份目录
# bakdir=/data/oss/backup-mn-sh/svn/repos/
bakdir=/data/app/svn/bak/
# 临时目录
cache_dir=.cache_baksvn
# 工作目录
workdir=/data/scripts/
# 是否全量备份
backup_all=false
# 每个文件包含版本数量
interval=1
# 日志目录
log_dir=${workdir}/log
# 日志文件
log_file=backup-$(date +%Y-%m-%d).log
if [ ${backup_all} == true ];then
# 备份月份
backup_month=$(date +%Y_%m)
# 备份日期
backup_date=$(date +%Y_%m_%d)
# 备份目录
bakdir=/data/oss/backup-mn-sh/svn/${backup_month}/${backup_date}
fi
# 运行主任务
mkdir -p ${workdir} && cd ${workdir}
mkdir -p ${log_dir} && main 2>&1 >> ${log_dir}/${log_file}
由于脚本中暂没实现自动化恢复,示例(恢复test仓库):
gunzip -c *.gz | svnadmin load /data/app/svn/data/test
构建
启动脚本
#!/bin/bash
#将备份在/data/salt中的数据备份到容器中的仓库,并启动脚本
bakdir='/data/svn/baksvn'
repodir='/data/svn/repos'
logfile='/data/svn/svn.log'
# 备份导入
if [ -d ${bakdir} ];then
repos_list=$(ls ${bakdir})
echo "初始化,正在导入svn备份文件..."
for repo in ${repos_list};
do
cd ${repodir} && svnadmin create ${repo}
for bakfile in $(ls ${bakdir}/${repo}/);
do
svnadmin load ${repo} < ${bakdir}/${repo}/${bakfile}
done
done
echo "导入完成!"
fi
# 启动服务
echo "正在启动服务..."
/usr/bin/svnserve -d -r ${repodir} --log-file ${logfile} && tail -f ${logfile}
# /usr/bin/svnserve -i -r ${repodir}
Dockerfile
FROM centos:7
USER root
WORKDIR /data/svn
RUN yum install -y subversion && \
svn --version && \
sed -i 's/# store-passwords = no/store-passwords = yes/g' /root/.subversion/servers && \
sed -i 's/# store-plaintext-passwords = no/store-plaintext-passwords = yes/g' /root/.subversion/servers && \
cp ~/.subversion/config ~/.subversion/config.bak && \
echo -e "[auth]\nstore-passwords = yes\n[helpers]\n[tunnels]\n[miscellany]\n[auto-props]\n" > ~/.subversion/config && \
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
ENV LC_ALL="zh_CN.UTF-8"
ENV LANG="zh_CN.UTF-8"
COPY ./deploy.sh .
CMD /bin/sh deploy.sh
svn 管理系统 - svnadmin
Dockerfile
FROM witersencom/svnadmin:2.5.8
RUN yum install openssh-clients sshpass -y
启动 svnadmin
#!/bin/bash
if [ ! -d "data" ];then
docker run -d --name svnadmintemp --privileged muen/svnadmin:2.5.8 /usr/sbin/init
docker cp svnadmintemp:/home/svnadmin ./data
docker cp svnadmintemp:/etc/httpd/conf.d ./data/
docker cp svnadmintemp:/etc/sasl2 ./data/
fi
mkdir -p data/ && chown -R 48.48 data/
docker rm -f svnadmin
docker run -d -p 6061:80 -p 3690:3690 \
--restart=always \
-v $(pwd)/data/:/home/svnadmin/ \
-v $(pwd)/data/conf.d/:/etc/httpd/conf.d/ \
-v $(pwd)/data/sasl2/:/etc/sasl2/ \
--privileged \
--name svnadmin \
muen/svnadmin:2.5.8
钩子
强制提交前备注
#!/bin/sh
REPOS="$1"
TXN="$2"
SVNLOOK="svnlook"
# SVN 提交必须填写备注钩子
LOGMSG=`$SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" | wc -c`
if [ "$LOGMSG" -lt 4 ];
then
echo -e "\nLog message cann‘t be empty! you must input more than 4 chars 4 Chinese characters as comment!\\n 日志消息不能为空!您必须输入超过4个字符或4个汉字以上作为注释!\\n" 1>&2
exit 1
fi
# All checks passed, so allow the commit.
exit 0
远程自动更新钩子
#!/bin/bash
# 路径带中文
export LC_CTYPE=en_US.UTF-8;
REPOS="$1"
TXN="$2"
SVNLOOK="/usr/bin/svnlook"
# 匹配该目录下的
SPATH="service/"
LOGPATH="/home/svnadmin/logs/post-commit.log"
FOUND=$($SVNLOOK changed "$REPOS" -r $TXN |awk '{print $2}'|grep -E "^$SPATH")
REMOTE_HOST="172.168.1.58"
REMOTE_USER="root"
REMOTE_PASSWORD="password"
REMOTE_SVN_USER="SVN"
REMOTE_SVN_PASSWORD="SVN_PASSWORD"
REMOTE_SVN_DIR="/data/salt/"
if [[ "$FOUND" == "" ]];then
exit 0;
else
echo "$(date -Iseconds) 自动更新仓库 $REPOS post-commit,版本:$TXN" >> $LOGPATH
sshpass -p $REMOTE_PASSWORD ssh -o StrictHostKeyChecking=no $REMOTE_USER@$REMOTE_HOST 'svn up --username ${REMOTE_SVN_USER} --password ${REMOTE_SVN_PASSWORD} $REMOTE_SVN_DIR'
fi