简单分享下我们之前的采用的基于git的开发上线流程,以及所采用的的上线脚本。流程只简单说下,只能希望是抛砖引玉了;上线脚本是本文“重点”。之所以想分享这套脚本,因为个人感觉这套脚本提供了一种目录间“备份--更新/同步--回滚”的实现思路,对其中的细节稍作修改,应该可以适用到其他地方。
总结了两张图来说明基于git的开发流程和上线流程
下面一起来看上线脚本
#!/bin/sh ###定义检查上一条命令是否执行成功的函数 function check { if [ $? -ne 0 ];then echo -e "\e[1;31m `date +%Y%m%d_%H:%M:%S` $1 exec failed,please check it ! \e[0m"|tee -a /root/shells/update_online/logs/www.err exit -1 fi } ips="192.xxx.xx.x 192.xxx.xx.x 192.xxx.xx.x" domain=www.xxx.com ###项目域名 app_base_dir=/app ###线上server:项目所在目录,如$app_base_dir/$app_dir拼起来即为项目所在绝对路径/app/www app_dir=www ###线上server:项目相对目录 local_dir=/home/update/to_online/www ###本地server:该目录是从远程git库检出的master分支,即“随时可上线的代码” bak_dir=/update_bak ###线上server:备份目录 cat <<update +------------------------------------------+ + A) 备份 + + B) 更新 + + C) 回滚 + + Q) 退出 + +------------------------------------------+ update read -p "请输入 (A|B|C|Q) ,再按ENTER键: " INPUT ###备份 if [ $INPUT = "A" ]; then for ip in $ips do ###在远程服务器备份,留三次的备份 echo -e "\e[1;33m\n-----------backup $ip $domain------------\e[0m" ssh $ip "if [ ! -z $bak_dir ] && [ ! -z $app_dir ];then\ mkdir $bak_dir &> /dev/null; cd $bak_dir; ls -d $base_dir*|sort -r|cat -n |awk '\$1 > 2 {print \$NF}'|xargs rm -rf; rsync -a --delete $app_base_dir/$app_dir/ $bak_dir/$app_dir-`date +%Y%m%d_%H.%M`/ --exclude 'xxx' --exclude 'xxx/xxx' else\ exit -1; fi" check "backup $ip $domain"; echo -e "\e[1;32m\n------backup $ip $domain success--------\e[0m\n" done ###更新 elif [ $INPUT = "B" ]; then ###拉取最新代码 echo -e "\e[1;33m\n---------------git pull--------------\e[0m" cd $local_dir git pull check "git pull"; echo -e "\e[1;32m\n-----------git pull success------------\e[0m" ###执行更新操作 for ip in $ips do echo -e "\e[1;33m----------update $ip $domain--------------\e[0m\n" cd $local_dir if [ ! -z $app_base_dir ] && [ ! -z $app_dir ];then ###此处因有--delete参数,故而先判断目录变量是否存在 rsync -avz --delete --exclude ".gitignore" --exclude ".git" ./ $ip:$app_base_dir/$app_dir/ check "rsync to $ip"; else exit -1 fi echo -e "\e[1;32m\n--------update $ip $domain success----------\e[0m" done ###回滚 elif [ $INPUT = "C" ]; then for ip in $ips do echo -e "\e[1;33m\n--------$ip $domain Start Rollback----------\e[0m" ###在远程获取备份目录的倒序排列,这里没有将命令集成到下面的远程命令代码块中是因为远程for i in `cat`操作需用单引号,进而无法使用awk,故而放到这里,多了一次ssh链接 ssh $ip "cd /update_bak && ls -d $base_dir*|sort -r|cat -n|awk '{print \"-\"\$1\",\"\$NF}' > /tmp/bak_dirs.txt" ssh $ip 'app_dir=www; app_base_dir=/app; app_dir=www; bak_dir=/update_bak; info_file=/tmp/bak_dirs.txt; ###以倒序排列记录备份目录的文件 unset bak_arr && declare -A bak_arr; ###定义以(-1,-2,-3)为key,以备份文件名称为value的关联数组 ###下面的for循环用于给关联数组赋值 for i in $(cat $info_file);do \ bak_arr[$(echo $i|cut -d "," -f 1)]=$(echo $i|cut -d "," -f 2); done; echo -e "\e[1;33m\n There are ${#bak_arr[@]} old version \n\e[0m"; cat $info_file|sed "s/,/) /"; ###显示本台机器上旧版本倒序排列 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;31m Your input is wrong !\e[0m"; elif [[ ! -d "$bak_dir/${bak_arr[$INPUT]}" ]];then \ echo -e "\e[1;31m $bak_dir/${bak_arr[$INPUT]} not exist ! \e[0m"; else \ ###执行回滚操作 cd $bak_dir/${bak_arr[$INPUT]}; rsync -av --delete ./ $app_base_dir/$app_dir/ --exclude "xxx" --exclude "xxx/xxx" fi' check "$ip rollback"; echo -e "\e[1;32m\n--------$ip $domain rollback success----------\e[0m" done elif [ $INPUT = "Q" ]; then echo -e "\n -----bye bye-----" exit 0 else exit 1 fi
以下是使用截图
备份:
回滚: