这个shell脚本是是我编写的第一代版本的增量代码上线脚本,现在代码上线脚本已更新了几个版本,关注的技术重点是可视化对代码版本任意回滚的上线系统(python语言编写),后期将逐步分享这些脚本^_^ 。虽然现在看来,这个脚本写的惨不忍睹,但是在当时却改变了公司的上线方式,从交接工作时的手动上线,改变为脚本自动化上线,也算是一个起点和转折点。
这个上线脚本功能比较简单,先请看上线总体流程:
以下是详细的上线流程图:
请使用"notepad++"或其它编辑器打开此文档, "alt+0"将函数折叠后方便查阅
#!/bin/sh #set -x #auther: gushao #time: 2014-5-30 #设置初始变量 #$1 参数说明 1 前台 2 后台 3 app #用于区分测试环境上线和生产环境上线 env_test=1 case $env_test in 1) REMOTE_IP=192.168.1.110 PARTS=22 #用于服务器重启时用 REMOTE_IP10=192.168.1.110 REMOTE_IP11=192.168.1.111 REMOTE_IP12=192.168.1.112 PARTS_RESIN10=22 PARTS_RESIN11=22 PARTS_RESIN12=22 ;; 2) REMOTE_IP=211.162.125.207 PARTS=1573 #用于服务器重启时用 REMOTE_IP10=211.***.125.2** REMOTE_IP11=211.***.125.*** REMOTE_IP12=211.**.125.*** PARTS_RESIN10=1573 PARTS_RESIN11=10011 PARTS_RESIN12=10012 ;; *) echo "输入参数有无,选择测试或正式环境" exit 1 ;; esac #中间路径变量 edir=`date +%Y-%m-%d`/`date +%H%M%S` rdate=`date +%Y-%m-%d_%H%M%S` NDATE=`date +%Y-%m-%d\ %H:%M:%S` DET_RYD=/home/resin/project_name #本地同步代码 DET_TOMCAT=/home/resin/tomcat/webapps DET_APP=/opt/tomcat_app/webapps #用于ssh同步时,需要同步到的目录 DET_RYD_HOME=/home/resin/ DET_TOMCAT_HOME=/home/resin/tomcat DET_APP_HOME=/opt/tomcat_app SOURCE_RYD="/home/demo/demo_ryd/project_name" #存放需要升级的代码路径 SOURCE_TOMCAT="/home/demo/demo_tomcat/webapps" SOURCE_APP="/home/demo/demo_app/webapps" #日志保存位置 LOG_RYD_BACK=/home/resin/log_back/project_name LOG_TOMCAT_BACK=/home/resin/log_back/tomcat LOG_APP_BACK=/home/resin/log_back/APP LOG_PATH=/home/resin/codeupdate.log #日志文件位置 #将改变的代码,从服务器上保存到制定的路径 REVAL_RYD=/home/resin/reval_back/ryd/ryd REVAL_TOMCAT=/home/resin/reval_back/tomcat/tomcat REVAL_APP=/home/resin/reval_back/app/app #保存这次上传的代码 CODE_RYD_BACK=/home/resin/code_bak/ryd/ryd CODE_TOMCAT_BACK=/home/resin/code_bak/tomcat/tomcat CODE_APP_BACK=/hom/resin/code_bak/app/app DEBUG=1 #调试模块,判断代码执行结果,指令执行出错后输出出错信息 function altert() { #usage:alert <$?> <object> if [ "$1" -ne 0 ] then echo "[warn]:$2 指令执行错误" >&2 echo "指令执行错误,请检查错误原因,继续请回车" read x fi } #此函数的做用是遍历$1的目录source,寻找$2目录中是否有一致的文件det,并输出不同的信息 #本脚本中此函数的变量$1为需要上传的文件,$2是服务器同步到本地的文件 function ergodic(){ #echo "$4" INIT_PATH=$3 #usage: ergodic $1 $2 $3=$1 for file in ` ls $1` do #此段代码的目的,是通过文本的方式完整文件或目录路径 echo ${1}/${file} > /tmp/tmp_wenijian.txt #然后将路径替换$1删除,替换为${DET}的路径 eval sed -i "s#${INIT_PATH}##" /tmp/tmp_wenijian.txt UNX=`cat /tmp/tmp_wenijian.txt | head -n 1` DET1=${2}$UNX path_a=${file} if [ -d ${1}/${file} ];then ergodic ${1}/${file} ${2} $3 $4 else #此代码段目的,用于无论循环到哪层目录,通过完成路径截取 echo ${1}/${file} > /tmp/tmp_wenijian.txt eval sed -i "s#${INIT_PATH}##" /tmp/tmp_wenijian.txt #unx是去除文件投的相对路径 UNX=`cat /tmp/tmp_wenijian.txt | head -n 1` DET1=${2}$UNX if [ -e ${DET1} ];then echo "[info][$NDATE]检测到改变文件:$UNX" | tee -a $LOG_PATH #此代码的目的是复制的时候讲文件的路径一起 cp --parent ${2}$UNX $4_${rdate} else echo "[warn][$NDATE]检测到新文件:$UNX" | tee -a $LOG_PATH fi fi done } #此函数的做用是遍历$1的目录,并对比$2中的文件,是否一致,输出不同的信息 function DIFF_RYD(){ INIT_PATH=$3 for file in ` ls $1` do echo ${1}/${file} > /tmp/tmp_wenijian.txt eval sed -i "s#${INIT_PATH}##" /tmp/tmp_wenijian.txt UNX=`cat /tmp/tmp_wenijian.txt | head -n 1` DET1=${2}$UNX path_a=${file} if [ -d ${1}/${file} ];then DIFF_RYD ${1}/${file} ${2} $3 else echo ${1}/${file} > /tmp/tmp_wenijian.txt eval sed -i "s#${INIT_PATH}##" /tmp/tmp_wenijian.txt UNX=`cat /tmp/tmp_wenijian.txt | head -n 1` DET1=${2}$UNX if [ -e ${DET1} ];then #比较上传到生产的文件和上传文件的差异 diff -q ${DET1} ${1}/${file} | tee -a $LOG_PATH else echo "[error][$NDATE]上传文件与本地文件不同步,请检测" | tee -a $LOG_PATH echo "[warn][$NDATE]检测到新文件:${1}/${file}" | tee -a $LOG_PATH fi fi done } #project_name上传代码,$1是需要上传的代码SOURCE,$2是本地的同步目录DET,$3是同步代码的上一级目录DET_HOME #$4是${CODE_BACK},$5是${LOG_BACK},$6是${REVAL},$7 remote_ip ,$8 port #$INIT_PATH是需要上传的代码,$DET是本地同步的代码,$DET_HOME是同步代码的上一级目录 function MODEL_UPLOAD() { #同步上产脚本主体函数 #预先创建各类自定义目录 test -e $2 || mkdir -p $2 test -e $4_${rdate} || mkdir -p $4_${rdate} test -e $5 || mkdir -p $5 test -e $6_${rdate} || mkdir -p $6_${rdate} test -e $1 || echo "[error][$NDATE]没有找到${2}部署文件" | tee -a $LOG_PATH test -e $1 || exit echo ‘%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%‘ > $LOG_PATH echo "[info][$NDATE]开始自动部署${2}版本上传" | tee -a $LOG_PATH chown -R resin:resin $1 #这个我定义的函数 ergodic $1 $2 $1 $6 chown -R resin:resin $2 echo "--------------------------------" | tee -a $LOG_PATH echo "判断两次同步期间${2}服务器是否有改动" | tee -a $LOG_PATH rsync -vzrtopg --delete --progress "-e ssh -p $PARTS" resin@$REMOTE_IP:$2 $3 | tee -a $LOG_PATH sleep 2 echo "第二次进行判断" rsync -vzrtopg --delete --progress "-e ssh -p $PARTS" resin@$REMOTE_IP:$2 $3 | tee -a $LOG_PATH echo "判断结束" | tee -a $LOG_PATH echo "-------------------" | tee -a $LOG_PATH echo "-----------------------------------------" echo "将本地文件同步到远程服务器" | tee -a $LOG_PATH rsync -vzrtopg --progress "-e ssh -p $PARTS" $1 resin@$REMOTE_IP:$3 | tee -a $LOG_PATH sleep 2 echo "第二次" rsync -vzrtopg --progress "-e ssh -p $PARTS" $1 resin@$REMOTE_IP:$3 | tee -a $LOG_PATH echo "------------------------------------------" | tee -a $LOG_PATH echo "将改变文件同步到本地服务器" | tee -a $LOG_PATH rsync -vzrtopg --progress "-e ssh -p $PARTS" $1 $3 | tee -a $LOG_PATH echo "--------------------------------------------------" #此操作用于对比上传的文件和服务器同步到本地文件是否一致 echo "将运程服务器与本地服务器同步" | tee -a $LOG_PATH rsync -vzrtopg --delete --progress "-e ssh -p $PARTS" resin@$REMOTE_IP:$2 $3 | tee -a $LOG_PATH sleep 2 echo "第二次" rsync -vzrtopg --delete --progress "-e ssh -p $PARTS" resin@$REMOTE_IP:$2 $3 | tee -a $LOG_PATH echo "------------------------------" | tee -a $LOG_PATH echo "文件检测开始:" | tee -a $LOG_PATH DIFF_RYD $1 $2 $1 echo "文件检测结束" | tee -a $LOG_PATH echo "-------------------------------------------------------------------------------------" | tee -a $LOG_PATH #将此次需要长传的文件打包保存 mv $1 $4_${rdate} echo "文件上传结束" #cat $LOG_PATH cat $LOG_PATH > $5/${rdate}.log } case $1 in 1) MODEL_UPLOAD $SOURCE_RYD $DET_RYD $DET_RYD_HOME $CODE_RYD_BACK $LOG_RYD_BACK $REVAL_RYD ;; 2) MODEL_UPLOAD $SOURCE_TOMCAT $DET_TOMCAT $DET_TOMCAT_HOME $CODE_TOMCAT_BACK $LOG_TOMCAT_BACK $REVAL_TOMCAT ;; 3) MODEL_UPLOAD $SOURCE_APP $DET_APP $DET_APP_HOME $CODE_APP_BACK $LOG_APP_BACK $REVAL_APP ;; *) echo "Usage:$0 {1project_name|2tomcat|3app}" | tee -a $LOG_PATH exit 1 ;; esac exit 0
这个shell脚本,算是初期练手之作,很难一下看明白是肯定的,整体写的很烂,但是在小地方的一些小技巧,确实可以让各位小伙伴们借鉴一下。
希望通过这系列的文章记录自己成长的脚步,没有谁能一下子就变成大牛,经过时间的打磨,让我们一步一步的脱变吧!!!
脚本不足之处:
1. 代码可读性太差
2. rsync执行是否完成正确性没有检查
3. rsync没有进行超时处理
本文出自 “运维路上” 博客,请务必保留此出处http://vekergu.blog.51cto.com/9966832/1698102
原文地址:http://vekergu.blog.51cto.com/9966832/1698102