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
Last Updated 8/27/2024, 12:42:48 PM