#!/bin/bash
# Source function library.
. /etc/init.d/functions
# 定义分割线
separator(){
for ((i=1;i<=100;i++))
do
echo -n "="
done
echo -e
}
separator
# 定义后端服务器列表
group_list="ip1 ip2"
# 定义变量
port="端口"
prog="****" # 项目目录名 格式java-xxx
prog_path="****" # 转发路径
package_name="****.war"
source_dir="${JENKINS_HOME}/jobs/${PROMOTED_JOB_NAME}/builds/${PROMOTED_NUMBER}/archive/contract-type-web/target"
source_file="${PROMOTED_JOB_NAME}/builds/${PROMOTED_NUMBER}/archive/contract-type-web/target/$package_name"
destination_dir="/data/icourt/project/backend"
logsprog="contract-type"
destination_log_dir="/data/logs"
back_dir="/data/icourt/backup/backend/$prog"
back_prog="backend-contract-type"
back_time=`date +"%Y-%m-%d-%s"`
script_dir="/usr/lib/systemd/system"
timecheck=$(date "+%Y-%m-%d %H:%M" | cut -b 1-15) # 过滤日志错误时间戳
NOW=`date +"%Y/%m/%d %T"`
echo -e "$NOW: 后端 $prog 代码上线将开始 ... "
# 动态创建启动脚本
service_script(){
cat > ${script_dir}/${prog}.service << EOF
[Unit]
Description=Spring-Cloud Web Application Container
After=syslog.target network.target
[Service]
Type=simple
User=tomcat
Group=tomcat
PIDFile=/var/run/${prog_path}.pid
ExecStart=/usr/bin/java -jar ${destination_dir}/${prog}/${package_name} -Xms1024M -Xmx1024M -server -XX:+UseParallelGC
SuccessExitStatus=143
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
}
# 检查探活页
check_Live(){
for n in $(seq 20)
do
sleep 15
echo "检查 'http://${node}:${port}/$prog_path/index.html' http 状态码 ... "
curl_status=`curl --max-time 1 -o /dev/null -s -w %{http_code} http://${node}:${port}/$prog_path/index.html`
echo "http 状态码 $curl_status ."
separator
salt $node cmd.run "grep -E -A 15 '${timecheck}' ${destination_log_dir}/${logsprog}/ssf-console.log | grep -E -A 15 'ERROR' | tail -n 50"
if [[ ${curl_status} -eq 404 ]]
then
echo "$node 后端 $prog 应用启动失败,http 状态码 :${curl_status},请查看 ${destination_log_dir}/${logsprog} 日志文件 !"
echo -e "拷贝 $package_name 到 $destination_dir 并删除代码目录 $destination_dir/$prog"
salt $node cmd.run "cd $destination_dir && cp -f $prog/$package_name . && rm -rf $prog"
echo "错误!退出当前脚本 …… "
exit 8
fi
if [[ ${curl_status} -eq 200 ]]
then
separator
echo "$node 后端 $prog 应用启动成功."
break
fi
NOW=`date +"%Y/%m/%d %T"`
echo "$NOW: 完成第 $n 次应用测试页检查 ... "
separator
done
}
# 第一次部署前测试能否正常启动
deploy_PreTest(){
cat << EOF
------------------------------------------------------
|********** 开始测试程序是否能正常启动 $prog **********|
------------------------------------------------------
EOF
echo -e "开发环境后端 $prog 代码 $package_name 在 $source_dir 目录下."
separator
echo -e "$node 进入测试程序步骤 ...\n$node '$destination_dir/$prog' 目录不存在,将新建代码目录 ... "
echo "salt $node file.mkdir $destination_dir/$prog"
salt $node file.mkdir $destination_dir/$prog
echo -e "当前将推送版本目录 '$source_dir'\n当前将推送版本文件 ' …… $source_file'\n目标目录 '$destination_dir/$prog'\n开始拷贝推送 $prog $package_name 到 $node ... "
echo -e "salt $node cp.get_file salt://$source_file $destination_dir/$prog/$package_name"
salt $node cp.get_file salt://$source_file $destination_dir/$prog/$package_name
echo -e "创建日志目录 $destination_log_dir/$logsprog"
echo -e "salt $node file.mkdir $destination_log_dir/$logsprog"
salt $node file.mkdir $destination_log_dir/$logsprog
salt $node cmd.run "chown -R tomcat:root $destination_log_dir/$logsprog"
echo -e "创建 $prog 服务启动文件"
service_script
mv ${script_dir}/${prog}.service /data/development/jenkins/jobs/service_dir
salt $node cp.get_file salt://service_dir/${prog}.service ${script_dir}/${prog}.service
echo "$node 开始启动 $prog 服务进行测试 ... "
salt $node service.start $prog
java_status=$(salt $node service.status ${prog} --out=json|awk 'NR==2 {print $NF}')
echo -e "服务状态 $java_status"
if [[ $java_status == 'true' ]]
then
echo "$node $prog 服务启动成功."
else [[ $java_status == 'false' ]]
echo "$node $prog 服务启动失败!"
echo -e "拷贝 $package_name 到 $destination_dir 并删除代码目录 $destination_dir/$prog"
salt $node cmd.run "cd $destination_dir && cp -f $prog/$package_name . && rm -rf $prog"
echo "错误!退出当前脚本 …… "
exit 7
fi
NOW=`date +"%Y/%m/%d %T"`
echo "$NOW: $node 测试代码部署完成,程序服务启动成功,开始检查应用测试页 ... "
check_Live
if [[ ${curl_status} -eq 200 ]]
then
echo "$node 后端 $prog 测试成功,接下来正式部署"
else
echo "$node 后端 $prog 测试失败,http 状态码 :${curl_status},请查看 ${destination_log_dir}/${logsprog} 日志文件!!!"
echo -e "拷贝 $package_name 到 $destination_dir 并删除代码目录 $destination_dir/$prog"
salt $node cmd.run "cd $destination_dir && cp -f $prog/$package_name . && rm -rf $prog"
echo "错误!退出当前脚本 …… "
exit 9
fi
}
# 进行部署的函数
deploy_Distribute(){
cat << EOF
------------------------------------------------------
|************ 开始部署开发环境后端 $prog ************|
------------------------------------------------------
EOF
echo -e "开发环境后端 $prog 代码 $package_name 在 $source_dir 目录下."
separator
echo "$node 检测备份目录是否已存在 ... "
chk_back_dir=$(salt $node file.directory_exists $back_dir --out=json|awk 'NR==2 {print $NF}')
echo 检测备份目录 = $chk_back_dir
if [[ $chk_back_dir == 'true' ]]
then
echo "$node '$back_dir' 备份目录已存在."
elif [[ $chk_back_dir == 'false' ]]
then
echo "$node '$back_dir' 备份目录不存在,将新建代码备份目录 ... "
salt $node file.mkdir $back_dir
else
echo "错误!现在退出脚本 …… "
exit 3
fi
echo "$node 检测 $prog 程序服务是否为可用 ... "
chk_java=$(salt $node service.available ${prog} --out=json|awk 'NR==2 {print $NF}')
echo 检测java = $chk_java
if [[ $chk_java == 'true' ]]
then
echo "$node $prog 服务可用并处于活跃状态,即将停止 $prog 服务 ... "
else [[ $chk_java == 'false' ]]
echo "$node $prog 服务不可用或不存在, 请检查 $prog 程序!"
echo "错误!现在退出 …… "
exit 4
fi
echo "开始停止 $prog 服务 ... "
salt $node service.stop ${prog}
java_status=$(salt $node service.status $prog --out=json|awk 'NR==2 {print $NF}')
echo java 服务状态 = $java_status
if [[ $java_status == 'false' ]]
then
echo "$node $prog 服务停止成功."
else [[ $java_status == 'true' ]]
echo "$node $prog 服务停止失败!"
echo "错误!现在退出脚本 …… "
exit 5
fi
echo "$node 删除之前版本 '$destination_dir/$package_name' 文件 ... "
salt $node file.remove $destination_dir/$package_name
echo -e "当前将推送版本目录 '$source_dir'\n当前将推送版本文件 ' …… $source_file'\n目标目录 '$destination_dir'"
echo -e "开始拷贝推送 $prog $package_name 到 $node ... "
salt $node cp.get_file salt://$source_file $destination_dir/$package_name
chk_copy=$(salt $node file.file_exists $destination_dir/$package_name --out=json|awk 'NR==2 {print $NF}')
echo 验证推送文件 = $chk_copy
if [[ $chk_copy == 'true' ]]
then
echo "推送 $prog $package_name 到 $node 成功."
else [[ $chk_copy == 'false' ]]
echo "拷贝 $prog $package_name 到 $node 失败!"
echo "错误!现在退出脚本 …… "
exit 6
fi
echo -e "$node 开始备份当前 $prog 代码 ... "
salt $node cmd.run "cd $destination_dir && zip -rq ${back_prog}.${back_time}.zip ./$prog && mv -v $destination_dir/${back_prog}.${back_time}.zip $back_dir"
echo -e "$node 开始部署 $prog 代码 ... "
salt $node cmd.run "cd $destination_dir && rm -rf $prog/*"
salt $node cmd.run "cp -v $destination_dir/$package_name $destination_dir/$prog && chown -R tomcat:root $destination_dir/$prog"
echo "$node 代码部署完成,开始启动 $prog 服务 ... "
salt $node service.start $prog
java_status=$(salt $node service.status ${prog} --out=json|awk 'NR==2 {print $NF}')
echo 服务状态 $java_status
if [[ $java_status == 'true' ]]
then
echo "$node $prog 服务启动成功."
else [[ $java_status == 'false' ]]
echo "$node $prog 服务启动失败!"
echo "错误!退出当前脚本 …… "
exit 7
fi
NOW=`date +"%Y/%m/%d %T"`
echo "$NOW: $node 代码部署完成,程序服务启动成功,开始检查应用测试页 ... "
check_Live
if [[ ${curl_status} -eq 200 ]]
then
continue
fi
separator
echo "$node 后端 $prog 应用启动失败,http 状态码 :${curl_status},请查看 ${destination_log_dir}/${logsprog} 日志文件!!!"
exit 9
}
# 总启动函数(判断项目目录是否存在)
# 根据判断项目目录判断是否第一次部署
main_Define(){
for node in $group_list;
do
separator
echo "$node 检测项目目录是否已存在 ... "
chk_prog_dir=$(salt $node file.directory_exists $destination_dir/$prog --out=json|awk 'NR==2 {print $NF}')
echo 检测代码目录 = $chk_prog_dir
if [[ $chk_prog_dir == 'true' ]]
then
echo "$node '$destination_dir/$prog' 目录已存在,将进行部署步骤"
deploy_Distribute # 部署
elif [[ $chk_prog_dir == 'false' ]]
then
echo "$node '$destination_dir/$prog' 目录不存在,将先进行测试程序步骤 ... "
deploy_PreTest # 测试
echo "$node 将进行部署步骤"
deploy_Distribute # 部署
separator
else
echo "错误!现在退出脚本 …… "
exit 2
fi
done
}
main_Define # 总启动
separator
NOW=`date +"%Y/%m/%d %T"`
echo -e "$NOW: 后端 $prog 代码部署上线任务完成."
separator