logo
tt's Note
  • 运维
    • 数据库
    • linux
    • vpn
    • 日志
    • 中间件
    • 服务
    • 监控
    • shell
    • windows
    • 语言
    • 云服务
    • 其他
  • 开发
    • 工具
  • 软件
    • 浏览器
    • 多端
    • win
    • mac
    • 网站
  • 项目
    • 效率工具
    • 兴趣
  • 脚本
    • jenkins
    服务概览
    ansible
    chrony时间服务器
    dnsmasq
    ffmpeg
    frp
    ftp
    gitea
    gitlab
    jenkins
    lsyncd
    minio(私有化oss)
    nacos
    nexus3(私有仓库)
    ossftp
    redmine
    registry(docker私有仓库)
    saltstack
    svn
    上一页saltstack

    #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