代码拉取完成,页面将自动刷新
#!/bin/bash
###############################################
#########自动部署shell实现代码#################
###############################################
# Node List 服务器节点
PRE_LIST='120.77.67.188' #"112.74.48.75" # 预生产节点
GROUP1_LIST=""
GROUP2_LIST=""
ROLLBACK_LIST="120.77.67.188"
# 日志日期和时间变量
LOG_DATE='date "+%Y-%m-%d"' # 如果执行的话后面执行的时间,此时间是不固定的,这是记录日志使用的时间
LOG_TIME='date "+%H-%M-%S"'
# 代码打包时间变量
CDATE=$(date "+%Y-%m-%d") # 脚本一旦执行就会取一个固定时间赋值给变量,此时间是固定的
CTIME=$(date +"%H-%M-%S")
# shell env 脚本位置等变量
SHELL_NAME="deploy.sh" # 脚本名称
SHELL_DIR="/home/hjs/deploy/" # 脚本路径
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log" # 脚本执行日志文件路径
# code env 项目相关代码变量
PRO_NAME="meinv" # 项目名称的函数
GIT_URL='https://gitee.com/hjsiamcer/meinv.git';
CODE_DIR="/deploy/code/"${PRO_NAME} # 从版本管理系统更新的代码目录
CONFIG_DIR="/deploy/config/"${PRO_NAME} # 保存不同项目的配置文件,一个目录里面就是一个项目的一个配置文件或多个配置文件
TMP_DIR="/deploy/tmp" # 临时目录
TAR_DIR="/deploy/tar" # 打包目录
LOCK_FILE="/tmp/deploy.lock" # 锁文件路径
usage(){ # 使用帮助函数
echo $"Usage: $0 [ init | pro_init | deploy | rollback [ list | emergency | version ]"
}
init(){ #部署服务器初始化
echo '初始化部署节点'
writelog '初始化部署节点(init)'
user=$(env|grep USER|cut -d "=" -f 2)
if [ "$user" != "root" ];then
echo '请使用root用户初始化部署服务器!'
exit 1;
fi
if [ ! -f "/deploy/deploy.lock" ];then
mkdir -p /deploy/code/ #项目git源码
mkdir -p /deploy/config/ #项目配置文件
mkdir /deploy/tmp/ #项目完整的干净的源码
mkdir /deploy/tar/ #项目全部版本的压缩包
touch /deploy/deploy.lock #创建锁问价
chown -R hjs.hjs /deploy
fi
}
pro_init(){ #项目初始化
#项目名
#项目git仓库地址
mkdir -p /deploy/code/${PRO_NAME}/
mkdir -p /deploy/config/${PRO_NAME}/base/
mkdir -p /deploy/config/${PRO_NAME}/other/
cd /deploy/code/${PRO_NAME} && git clone ${GIT_URL} .
}
writelog(){ # 写入日志的函数
LOGINFO=$1 # 将参数作为日志输入
echo "${CDATE} ${CTIME} : ${SEHLL_NAME} : ${LOGINFO}" >> ${SHELL_LOG}
}
# 锁函数
shell_lock(){
touch ${LOCK_FILE}
}
# 解锁函数
shell_unlock(){
rm -f ${LOCK_FILE}
}
# 获取代码的函数
code_get(){
echo "code_get"
writelog 'code_get' #写入日志
cd $CODE_DIR && git pull # 进入到代码目录更新代码,此处必须免密码更新,此目录仅用于代码更新不能放其他任何文件
}
code_build(){ # 代码编译函数
echo 'code_build'
writelog '编译(code build)'
}
code_config(){ # 将配置文件放到源代码中,然后将当前版本代码放到tmp目录并且重命名
writelog "code_config"
#/bin/cp -rf ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}" # 将配置文件放在本机保存配置文件的临时目录,用于暂时保存代码项目。之所以使用/bin/cp不使用cp是为了强制复制
cd $CODE_DIR
cp -rf ${CODE_DIR} ${TMP_DIR}/ # 将代码放到临时保存目录,包名为时间+版本号,准备复制到web服务器
API_VERL=$(git show | grep commit | cut -d ' ' -f2)
API_VER=$(echo ${API_VERL:0:8}) #版本号。 使用从仓库commit id的前8位作为版本号
PKG_NAME="${PRO_NAME}"_"$API_VER"_"${CDATE}-${CTIME}" # 定义代码目录名称
cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME} #切换到临时目录, 重命名代码文件为web-demo_123-20170629-11-19-10格式
}
code_tar(){ # 对代码打包函数
writelog '代码打包(code_tar)'
cd ${TMP_DIR} && tar czf ${PKG_NAME}.tar.gz ${PKG_NAME} --exclude=".git" # 将目录打包成压缩文件,便于网络传输,并且排除.git目录
PKG_NAME="${PRO_NAME}"_"$API_VER"_"${CDATE}-${CTIME}" # 定义代码目录名称
cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME} #切换到临时目录, 重命名代码文件为web-demo_123-20170629-11-19-10格式
}
code_scp(){ # 代码压缩包scp到客户端的函数
writelog "代码发布到客户端节点(code_scp)"
for node in $PRE_LIST;do # 循环预生产服务器节点列表
scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/ # 将压缩后的代码包复制到web服务器的/opt/webroot
done
for node in $GROUP1_LIST;do # 循环生产服务器节点列表
scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/ # 将压缩后的代码包复制到web服务器的/opt/webroot
done
}
cluster_node_add(){ #将web服务器添加至集群
echo '将web服务器添加至集群'
writelog "将web服务器添加至集群(cluster_node_add)"
}
cluster_node_remove(){ # 将web服务器从集群移除函数(正在部署的时候应该不处理业务)
echo '将web服务器从集群移除: ' ${1}
writelog " 将web服务器从集群移除(cluster_node_remove):${1}"
}
url_test(){
URL=$1
curl -s --head $URL |grep '200 OK'
if [ $? -ne 0 ];then
shell_unlock;
writelog "test error" && exit;
fi
}
pre_deploy(){ # 代码解压部署函数,预生产节点
writelog "预生产节点部署(pre_deploy)"
for node in ${PRE_LIST};do # 循环预生产服务器节点列表
cluster_node_remove ${node} # 部署之前将节点从前端负载删除
echo "预生产节点部署:pre_deploy, cluster_node_remove ${node}"
ssh ${node} "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz" #分别到web服务器执行压缩包解压命令
#删除旧的软连接,并创建新的软连接指向新解压出来的代码:/webroot/web/demo-->/opt/webroot/web-demo_xxxx
ssh ${node} "rm -f /webroot/${PRO_NAME} && ln -s /opt/webroot/${PKG_NAME} /webroot/${PRO_NAME}" # 整个自动化的核心,创建软连接。
done
}
pre_test(){ # 预生产主机测试函数
for node in ${PRE_LIST};do # 循环预生产主机列表
curl -s --head http://${node}:9999/index.html | grep "200 OK" # 测试web界面访问
if [ $? -eq 0 ];then # 如果访问成功
writelog " ${node} Web Test OK!" # 记录日志
echo " ${node} Web Test OK!"
cluster_node_add ${node} # 测试成功之后调用添加函数把服务器添加至节点,
writelog "pre,${node} add to cluster OK!" # 记录添加服务器到集群的日志
else # 如果访问失败
writelog "${node} test no OK" # 记录日志
echo "${node} test not OK"
shell_unlock # 调用删除锁文件函数
break # 结束部署
fi
done
}
group1_deploy(){ # 代码解压部署函数.集群1
writelog "group1_code_deploy"
for node in ${GROUP1_LIST};do # 循环生产服务器节点列表
cluster_node_remove $node
echo "group1, cluster_node_remove $node"
ssh ${node} "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz" # 分别到各web服务器节点执行压缩包解压命令
ssh ${node} "rm -f /webroot/${PRO_NAME} && ln -s /opt/webroot/${PKG_NAME} /webroot/${PRO_NAME}" # 整个自动化的核心,创建软连接
done
# scp ${CONFIG_DIR}/other/192.168.3.13.server.xml 192.168.3.13:/webroot/web-demo/server.xml # 将差异项目的配置文件scp到此web服务器并以项目结尾
}
group1_test(){ # 生产主机测试函数。集群1
for node in ${PRE_LIST};do # 循环生产主机列表
curl -s --head http://${node}:9999/index.html | grep "200 OK" #测试web界面访问
if [ $? -eq 0 ];then #如果访问成功
writelog " ${node} Web Test OK!" #记录日志
echo "group1_test,${node} Web Test OK!"
cluster_node_add
writelog " ${node} add to cluster OK!" #记录将服务器 添加至集群的日志
else #如果访问失败
writelog "${node} test no OK" #记录日志
echo "${node} test no OK"
shell_unlock # 调用删除锁文件函数
break # 结束部署
fi
done
}
emergency_code_get(){ #获取代码的函数
writelog "code_get"
cd ${CODE_DIR} && git reset --hard HEAD^ #进入到代码目录更新代码,此处必须免密码更新,此目录仅用于代码更新不能放其他任何文件
/bin/cp -rf ${CODE_DIR} ${TMP_DIR}/ #临时保存代码并重命名,包名为时间+版本号,准备复制到web服务器
API_VERL=$(git show | grep commit | cut -d ' ' -f2)
API_VER=$(echo ${API_VERL:0:8}) #取八位
}
emergency(){ #紧急回退到上一个版本函数
echo "紧急回退(emergency)"
shell_lock; # 执行部署之前创建锁。如果同时有其他人执行则提示锁文件存在
emergency_code_get; # 获取代码
code_build; # 如果要编译执行编译函数
code_config; # cp配置文件
code_tar; # 打包
code_scp; # scp到服务器
pre_deploy; # 预生产环境部署
#pre_test; # 预生产环境测试
group1_deploy; # 生产环境部署
# group1_test; # 生产环境测试
shell_unlock; # 执行完成后删除锁文件
}
rollback_fun(){
for node in $ROLLBACK_LIST;do # 循环服务器节点列表
# 注意一定要加"号,否则无法在远程执行命令
ssh $node "rm -f /webroot/${PRO_NAME} && ln -s /opt/webroot/$1 /webroot/${PRO_NAME}" # 立即回滚到指定的版本,$1即指定的版本参数
echo "${node} rollback success!"
done
}
rollback(){ # 代码回滚主函数 如果回滚参数是list就可以查看当前可以回滚的版本
if [ -z $1 ];then
shell_unlock # 删除锁文件
echo "请输入需要回滚的版本号" && exit 3;
fi
case $1 in # 把第二个参数做当自己的第一个参数
list) #从这里可以看到所有的版本,这些版本在每个节点的/opt/webroot目录也存在,但是这也不能绝对保证
ls -l /deploy/tmp/*.tar.gz | grep ${PRO_NAME}
;;
*)
rollback_fun $1
esac
}
# 主函数
main(){
if [ -f $LOCK_FILE ];then # 先判断锁文件在不在
echo "Deploy is running" && exit 10; # 如果有锁文件直接退出
fi
DEPLOY_METHOD=$1 # 避免出错误将脚本的第一个参数作为变量
ROLLBACK_VER=$2
case $DEPLOY_METHOD in
init)
init; #部署服务器初始化
;;
pro_init)
pro_init; #项目初始化
;;
deploy) # 如果第一个参数是deploy就执行以下操作
shell_lock; # 执行部署之前创建锁。如果同时有其他人执行则提示锁文件存在
code_get;
code_build; # 如果要编译执行编译函数
code_config; # cp配置文件
code_tar; # 打包
code_scp; # scp到服务器
pre_deploy; # 预生产环境部署
#pre_test; # 预生产环境测试
group1_deploy; # 生产环境部署
# group1_test; # 生产环境测试
shell_unlock; # 执行完成后删除锁文件
;;
rollback) # 如果第一个参数是rollback就执行以下操作
shell_lock; # 回滚之前也是先创建锁文件
rollback $ROLLBACK_VER; # 执行完成删除锁文件
shell_unlock;
;;
*) # 其他输入执行以下操作
usage;
esac
}
# 执行主函数并把第一个变量当参数
main $1 $2
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。