基於git+rsync的代碼--備份/上線/回滾--腳本一例

簡單分享下我們之前的採用的基於git的開發上線流程,以及所採用的的上線腳本。流程是個大問題,這裏只簡單說下只能希望是拋磚引玉了;上線腳本是本文“重點”。之所以想分享這套腳本,因爲個人感覺這套腳本提供了一種目錄間“備份–更新–回滾”的實現思路,對其中的細節稍作修改,應該可以適用到其他地方。

這一篇算是改進版,之前是一個項目一個腳本,其實裏面邏輯基本一致,只是由於項目標準化度不夠,導致無法統一管理。後來經過對開發測試生產環境進行一番規範統一之後,可以做到用一個腳本來管理所有項目的“備份-上線-回滾”操作

一些可參考的規範標準: (有些與本文無關了,但是這裏一併寫出來,規範化是自動化的前提)

項目在各環境的目錄結構儘量保持一致

項目名稱均取主域名之前的部分,例如api.baidu.com,則項目目錄命名爲api

nginx(舉例)各虛擬主機的配置文件命名爲上述項目名稱.conf

項目框架儘量保持版本一致

下面開始正文:總結了兩張圖來說明基於git的開發流程和上線流程
image
image

下面一起來看上線腳本

#!/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=""    
fi

if [[ $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 -1
elif [[ $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
    fi
else
    echo -e "\e[1;31m-----------\n該腳本只適用於(api|i|interface|m|news)\n------------\e[0m"
    exit -1
fi

function 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) 退出                  +
+------------------------------------------+
update

read -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"
    done

elif [ $INPUT = "Q" ]; then 
    echo -e "\n -----bye bye-----"
    exit 0
else
    exit 1
fi

以下是使用截圖:
備份:
image
更新:
image
回滾:
image

發佈了50 篇原創文章 · 獲贊 33 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章