当先锋百科网

首页 1 2 3 4 5 6 7

对于jenkins自动化部署已经很熟悉,之前工程都是打war包,通过jenkins打包后,将war放到指定目录,然后用简单的脚本启动tomcat即可。

本次对于工程进行了SpringBoot改造,打成JAR包,可以不依赖外部的tomcat,直接通过java -jar命令启动。

于是想到重新写一份shell脚本来实现自动停止服务,自动备份jar包,然后启动jar包,并借助actuator提供的监控功能,判断工程是否正常。

总体思路大概是:

1、将已启动的工程停掉

在这个过程就遇到个小问题,之前都是直接通过ps查询指定进程,然后kill -9即可。

但是如果当前没有正在启动的工程实例,则该语句会报错,不够友好。所以增加了进程数量的判断逻辑。

2、停掉服务后,先备份旧的jar包,然后将新jar包copy到指定位置

这个过程也可能有问题,如果新的jar没有cp成功,脚本仍然会继续往下走,也不够友好。

所以此处需要判断cp命令有没有正常执行

3、后台方式启动jar工程(注意必须是nohub方式,否则shell会一直卡自此处,工程在当前用户实例下运行)

需要注意,为了能够查看到启动日志,需要将所有日志输出到指定文件

4、通过actuator检查服务状态

可以借助curl命令,直接访问xxx/actuator/health,判断服务状态。

但是遇到了几个小问题,首先是在服务还在启动过程中,访问服务地址是无效的,因为端口还没启动,会直接返回,提示Could not connect to host,而不是等待。

所以此时,直接使用curl会立即返回状态码000。为了解决这个问题,就需要每隔一段时间进行检查一下,一直等待服务真正启动。(但是需要设置循环等待的次数限制)

如果没有出现200,则等待一会,继续下一次检查。如果出现200,则获取health返回的JSON数据。

然后就需要考虑如何解析JSON了,有两种方式,一种是简单粗暴,直接判断JSON字符串中是否有特定的字符串,来判断状态是否OK

另一种更优雅的方式则是解析JSON,在shell里,我们可以借助PYTHON脚本来进行JSON的解析,获取指定的返回值。然后判断服务的各种运行情况。

#!/bin/bash

pid_name="ccc"
profile="test"
healthUrl=http://localhost:8080/actuator/health


# stop application
echo -e "\033[32m>>>>>>>>>>>>>>>>>> stop ccc application ...\033[0m"

# ps -ef| grep java | grep $pid_name|grep -v grep|awk '{print $2}'|xargs kill -9
count=$(ps -ef | grep java | grep $pid_name | grep -v grep | wc -l)

if [ $count -eq 0 ]; then
  echo -e "\033[33m>>>>>>>>>>>>>>>>>> application not running.\033[0m"
else
  ps -ef| grep java | grep $pid_name|grep -v grep|awk '{print $2}'|xargs kill -9
  if [ "$?" = "0" ]; then
    echo -e "\033[32m>>>>>>>>>>>>>>>>>> application stopped ...\033[0m"
  else
    echo -e "\033[31m<<<<<<<<<<<<<<<<<< application stop failed.\033[0m"
    exit 9
  fi
fi
sleep 5


# copy jar

echo -e "\033[32m>>>>>>>>>>>>>>>>>> backup jar file ...\033[0m"
mv JAR_PATH/ta.jar JAR_PATH/backup/ccc_$(date +'%Y%m%d%H%M%S').jar

echo -e "\033[32m>>>>>>>>>>>>>>>>>> copy new jar file ...\033[0m"
cp WORK_DIR_PATH/jenkins/ccc.jar WORK_DIR_PATH/ccc.jar

if [ "$?" = "0" ]; then
  echo -e "\033[32m>>>>>>>>>>>>>>>>>> backup & copy done.\033[0m"
else
  echo -e "\033[31m<<<<<<<<<<<<<<<<<< backup & copy failed.\033[0m"
  exit 9
fi

# start application
echo -e "\033[32m>>>>>>>>>>>>>>>>>> starting ccc application ...\033[0m"

nohup java -XX:+HeapDumpOnOutOfMemoryError -Xms2g -Xmx4g -Xmn2g -jar WORK_DIR_PATH/ccc.jar --spring.profiles.active=$profile --spring.config.location=classpath:/,/ta/runtime/application-$profile.yml &>WORK_DIR_PATH/startup.log &

# check status
echo -e "\033[32m>>>>>>>>>>>>>>>>>> checking status...\033[0m"
# check times
times=20
for i in $(seq 1 $times); do
  sleep 10
  httpCode=$(curl -I -o /dev/null -s -w %{http_code} $healthUrl)
  if [ $httpCode -eq 200 ]; then
    break
  fi
  echo -e "\033[32m>>>>>>>>>>>>>>>>>> checking status...\033[0m"
done

if [ $httpCode -eq 200 ]; then
  resp=$(curl -s $healthUrl)
  status=$(echo $resp | python -c "import sys,json; print(json.load(sys.stdin)['status']['code'])")
  if [ $status = "UP" ]; then
    echo -e "\033[32m>>>>>>>>>>>>>>>>>> application started ...\033[0m"
  else
    sleep 10

    resp=$(curl -s $healthUrl)
    status=$(echo $resp | python -c "import sys,json; print(json.load(sys.stdin)['status']['code'])")
    if [ $status = "UP" ]; then
      echo -e "\033[32m>>>>>>>>>>>>>>>>>> application started ...\033[0m"
    else
      echo -e "\033[31m>>>>>>>>>>>>>>>>>> start failed ...\033[0m"
      exit
    fi
  fi
else

  echo -e "\033[31m>>>>>>>>>>>>>>>>>>>>>> can not check status, httpCode: $httpCode\033[0m"
fi

echo -e "\033[32m=============== deploy done!!! ...\033[0m"