logo
关于我们

技术分享

技术分享 基于git+rsync的代码--备份/上线/回滚--脚本一例

基于git+rsync的代码--备份/上线/回滚--脚本一例

2020-04-24

简单分享下我们之前的采用的基于git的开发上线流程,以及所采用的的上线脚本。流程是个大问题,这里只简单说下只能希望是抛砖引玉了;上线脚本是本文“重点”。之所以想分享这套脚本,因为个人感觉这套脚本提供了一种目录间“备份–更新–回滚”的实现思路,对其中的细节稍作修改,应该可以适用到其他地方。

这一篇算是改进版,之前是一个项目一个脚本,其实里面逻辑基本一致,只是由于项目标准化度不够,导致无法统一管理。后来经过对开发测试生产环境进行一番规范统一之后,可以做到用一个脚本来管理所有项目的“备份-上线-回滚”操作

一些可参考的规范标准: (有些与本文无关了,但是这里一并写出来,规范化是自动化的前提)

项目在各环境的目录结构尽量保持一致

项目名称均取主域名之前的部分,例如api.baidu.com,则项目目录命名为api

nginx(举例)各虚拟主机的配置文件命名为上述项目名称.conf

项目框架尽量保持版本一致

下面开始正文:总结了两张图来说明基于git的开发流程和上线流程

基于git+rsync的代码--备份/上线/回滚--脚本一例


基于git+rsync的代码--备份/上线/回滚--脚本一例

下面一起来看上线脚本

#!/bin/sh###########by ljk 20161017#该脚本运行的前提是项目名称在本地和远程均统一规范:均取域名中".baidu.com"前面的部分,如api.baidu.com,项目名为api#项目在本地及远程的目录统一规范:#    在本地各项目均位于/home/update/to_online下#    在远程各项目均位于/app下#远程备份目录统一规范:均为/update_bak##########app_name=$1###定义本地相关目录local_base_dir="/home/update/to_online"    #项目的本地目录ip_file="/root/tongbu_to_online/ip/$app_name"    #包含该站点信息'server_name-ip:port'格式的文件exclude_files="/root/tongbu_to_online/exclude/$app_name"    #该站点上线(rsync)所要排除的文件error_log="/root/tongbu_to_online/error/$app_name"    #该站点上线错误日志###定义远程目录等变量domain="$app_name".baidu.com    ###项目域名remote_base_dir="/app"    #远程项目目录的父目录bak_dir="/update_bak"    #远程备份的目录if [[ $app_name =~ ^(api|i|interface|m)$ ]];then
    #根据项目名成确定在远程备份和回滚时使用到的--exclude参数,这里因为我的项目无法再更进一步规范统一,只能加判断
    backup_rollback_exclude="--exclude 'app/storage' --exclude 'storage'"elif [ $app_name = user ];then
    backup_rollback_exclude="--exclude 'uploadPhoto.log'"elif [[ $app_name =~ ^(acg|api)$ ]];then
    backup_rollback_exclude=""    fiif [[ $app_name =~ ^(api|acg|user)$ ]];then
    #根据项目名成确定初始化配置文件的操作
    alias init_config='ssh -p$port $ip "cd /$remote_base_dir/$app_name/ && sh init.sh production"'else
    alias init_config=''fi###检查用户参数输入if [ $# -ne 1 ];then
    echo -e "\e[1;31m-----------\n参数不正确,请输入要上线项目的名称(取域名中\".baidu.com\"前面的部分,如api.baidu.com,项目名为api)\n------------\e[0m"
    exit -1elif [[ $1 =~ ^(api|i|interface|m|news)$ ]];then
    if [ ! -d $local_base_dir/$1 ];then
        echo -e "\e[1;31m-----------\n本地目录$local_base_dir/$1不存在\n------------\e[0m"
        exit -1
    fielse
    echo -e "\e[1;31m-----------\n该脚本只适用于(api|i|interface|m|news)\n------------\e[0m"
    exit -1fifunction check {    #定义一个函数用于检查上一步执行是否成功
    if [ $? -ne 0 ];then 
            echo -e "\e[1;31m `date +%Y%m%d_%H:%M:%S`  $1 failed,please check it ! \e[0m"|tee -a $error_log
            exit -1
    fi}###主要功能开始cat <<update
+------------------------------------------+
+                 A) 备份                  +
+                 B) 更新                  +
+                 C) 回滚                  +
+                 Q) 退出                  +
+------------------------------------------+
updateread -p "请输入 (A|B|C|Q) ,再按ENTER键: " INPUT###备份if [ $INPUT = "A" ]; then

    for info in `cat $ip_file`; do
        server=`echo $info|awk -F [-:] '{print $1}'`
        ip=`echo $info|awk -F [-:] '{print $2}'`
        port=`echo $info|awk -F [-:] '{print $3}'`        ###在远程服务器备份,并删除三次前的备份
        echo -e "\e[1;33m\n-----------backup  $server $domain------------\e[0m"
        sleep 1
        ssh -p$port root@$ip "if [ ! -z $bak_dir ] && [ ! -z $remote_base_dir/$app_name ];then\
                                  mkdir $bak_dir &> /dev/null; cd $bak_dir;
                                  ls -d $app_name*|sort -r|cat -n|awk '\$1 > 2 {print \$NF}'|xargs rm -rf;    ###按文件名称倒序排列,删除两个以后的
                                  rsync -av --delete $remote_base_dir/$app_name/ /update_bak/$app_name-`date +%Y%m%d_%H.%M`/ $backup_rollback_exclude;
                              else
                                  exit -1;
                              fi"

        check "backup $server $domain";        echo -e "\e[1;32m------backup $server $domain success--------\e[0m\n"
   done###更新elif [ $INPUT = "B" ]; then

    ###拉取最新代码
    echo -e "\e[1;33m\n---------------git pull--------------\e[0m"
    cd $local_base_dir/$app_name
    git pull
    check "git pull";    echo -e "\e[1;32m\n-----------git pull success------------\e[0m"
    #chown -R www.www $local_base_dir/$app_name/storage || chown -R www.www $local_base_dir/$app_name/app/storage
    #check "chown www storage";
    sleep 5

    for info in `cat $ip_file`; do
        server=`echo $info|awk -F [-:] '{print $1}'`
        ip=`echo $info|awk -F [-:] '{print $2}'`
        port=`echo $info|awk -F [-:] '{print $3}'`        echo -e "\e[1;33m\n----------update $server $domain--------------\e[0m\n"

        if [ ! -z $local_base_dir/$app_name ];then
            rsync -e "ssh -p $port" -avz --delete --exclude-from=$exclude_files   ./  root@$ip:$remote_base_dir/$app_name/
            check "rsync to $ip";        else
            echo -e "\e[1;31m\n----------$server remote '$local_base_dir/$app_name' is empty--------------\e[0m\n"
            exit -1
        fi
        init_config    echo -e "\e[1;32m--------update $server $domain success----------\e[0m"
    done###回滚elif [ $INPUT = "C" ]; then
    for info in `cat $ip_file`; do
        server=`echo $info|awk -F [-:] '{print $1}'`
        ip=`echo $info|awk -F [-:] '{print $2}'`
        port=`echo $info|awk -F [-:] '{print $3}'`        echo -e "\e[1;33m\n--------$server Start Rollback----------\e[0m"

        ssh -p$port root@$ip "
                              cd $bak_dir && find . -maxdepth 1 -type d -name \"$app_name*\"|sort -r|awk -F'/' '{print \$NF}'|cat -n|awk '{print \"-\"\$1\") \"\$NF}' > /tmp/$app_name-bak_dirs.txt;    #在远程获取备份目录的倒序排列
                              info_file=/tmp/$app_name-bak_dirs.txt;    #以倒序排列记录备份目录的文件,由‘更新’步骤生成
                              unset bak_arr && declare -A bak_arr;    #定义以(-1,-2,-3)位key,以备份文件名称为value的关联数组

                              ###下面的for循环用于给关联数组赋值
                              while read i;do \
                                  bak_arr[\$(echo \$i|awk -F') ' '{print \$1}')]=\$(echo \$i|awk -F') ' '{print \$2}');
                              done < \$info_file;

                              echo -e \"\e[1;33m\n There are \${#bak_arr[@]} old version \n\e[0m\";
                              cat \$info_file;    ###显示本台机器上旧版本倒序排列
                              echo -e \"\e[1;33m\n Which one do you want to roolback ?\n Input one of \"-1, -2, -3\"\n \e[0m\";
                              read INPUT;

                              ###下面对输入以及目录存在性做判断
                              if [ -z \${bak_arr[\$INPUT]} ];then \
                                  echo -e \"\e[1;31mYour input is wrong\e[0m\";
                                  exit 100;
                              elif [ ! -d $bak_dir/\${bak_arr[\$INPUT]} ];then \
                                  echo -e \"\e[1;31m$bak_dir/\${bak_arr[\$INPUT]} not exist \e[0m\";
                                  exit 200;
                              else \
                                  ###执行回滚操作
                                  cd $bak_dir/\${bak_arr[\$INPUT]};
                                  rsync -av --delete ./ $remote_base_dir/$app_name/ $backup_rollback_exclude;
                              fi"

        check "$server rollback";        echo -e "\e[1;32m\n--------rollback $server success----------\e[0m"
    doneelif [ $INPUT = "Q" ]; then 
    echo -e "\n -----bye bye-----"
    exit 0else
    exit 1fi

以下是使用截图:
备份:

基于git+rsync的代码--备份/上线/回滚--脚本一例


更新:

回滚:

基于git+rsync的代码--备份/上线/回滚--脚本一例


云祺备份软件,云祺容灾备份系统,虚拟机备份,数据库备份,文件备份,实时备份,勒索软件,美国,图书馆
  • 标签:
  • 其他

您可能感兴趣的新闻 换一批

现在下载,可享30天免费试用

立即下载