项目结构

├─bin
│  └─app.sh
│  ├─shutdown.cmd
│  ├─shutdown.sh
│  ├─startup.cmd
│  └─startup.sh
├─config
├─lib
├─logs
├─target
└─temp

背景

在spring boot 服务实际部署过程中,发现老版本脚本的很多问题
问题:

  • 只能在项目目录启动脚本
  • 项目可能在同一服务器部署了多套,没办法兼容
  • 没办法通过ps -ef 一次观测到项目目录
  • logs文件必须手动创建问题

lib 目录生成

mvn dependency:copy-dependencies -DoutputDirectory=lib

pom.xml

    <build>
        <resources>
            <!-- 编译之后包含xml   -->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <testResources>
            <testResource>
                <directory>src/test/resources</directory>
            </testResource>
        </testResources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includes>
                        <include>
                            <groupId>nothing</groupId>
                            <artifactId>nothing</artifactId>
                        </include>
                    </includes>
                    <layout>ZIP</layout>
                </configuration>
            </plugin>
        </plugins>
        <finalName>${project.artifactId}</finalName>
    </build>

使用方式

修改脚本中的SERVICE_NAME的值即可

app.sh

#!/bin/sh

##项目服务名称

SERVICE_NAME=-server

## 脚本所在目录
BASEPATH=$(
  cd $(dirname $0)
  cd ..
  pwd
)

## 以脚本所在目录为执行目录
cd $BASEPATH

## 相关Config

JAR_NAME=$SERVICE_NAME\.jar

JAR_HOME=$BASEPATH/target/

JAR_PATH=$JAR_HOME$JAR_NAME

##pid监控文件 内容是程序的pid
PID=$BASEPATH/bin/$SERVICE_NAME\.pid

## 日志文件名称
LOG_NAME=app.log

##服务目录
SERVICE_LOGS=logs

SERVICE_LOGS_HOME=$SERVICE_LOGS/

LOG_FILE_PATH=$SERVICE_LOGS_HOME$LOG_NAME

##GC.log日志
GC_LOG=$SERVICE_LOGS/gc.log

JAVA_OPTS=""

## 配置外部化lib
JAVA_OPTS=$JAVA_OPTS"-Dloader.path=lib/ "

## 配置GC信息
JAVA_OPTS=$JAVA_OPTS"-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$GC_LOG "

## 配置JVM堆栈相关参数
JAVA_OPTS=$JAVA_OPTS"-ms512m -mx512m -Xmn256m -Djava.awt.headless=true -XX:MaxPermSize=128m "



## 使用说明,用来提示输入参数
usage() {
  echo "Usage: sh 执行脚本.sh [start|stop|restart|status]"
  # 退出
  exit 1

  ## help
  ## $? 是上个函数返回值
  ## Shell中判断语句if中-z至-d的意思 https://www.cnblogs.com/coffy/p/5748292.html
}

## 检查程序是否在运行
is_exist() {
  ## grep -v 排除 grep字段
  pid=$(ps -ef | grep -F $JAR_NAME | grep -v grep | awk '{print $2}')
  ## 单个服务器部署了多个相同名称项目的话 只根据PID文件进行服务状态判断
  ## pid=cat $PID
  if [[ -z "$pid" ]]; then
    rm -rf $PID
  fi
  return $pid
}

#启动方法

init() {
  ## 判断logs目录是否存在,不存在则创建
  if [ ! -d "$SERVICE_LOGS_HOME" ]; then
    mkdir -p $SERVICE_LOGS_HOME
  fi

  if [ ! -f "$LOG_FILE_PATH" ]; then
    touch $LOG_FILE_PATH
  fi
}

start() {
  is_exist
  init
  if [ ! -f "$PID" ]; then
    # echo "java  $JAVA_OPTS -jar  $JAR_PATH >/dev/null 2>&1 &"
    # nohup java $JAVA_OPTS -jar $JAR_PATH >catalin.log 2>&1 &
    nohup java  $JAVA_OPTS -jar  $JAR_PATH >/dev/null 2>&1 &
    echo $! >$PID
    ## 根据传参 判断 是自动构建工具还是直接运行  构建工具 需要睡眠5s,然后 打印出最后100行
    if [[ $1 == "ci" ]]; then
      sleep 10s
      tail -n 100 $LOG_FILE_PATH
    else
      tail -0f $LOG_FILE_PATH
    fi
    echo ">>> start $JAR_NAME successed PID=$! <<<"
  else
    echo ">>> $JAR_NAME  already start <<<"
    status
  fi
}

#停止方法 根据pid文件停止进程
stop() {

  is_exist
  if [[ -z "$pid" ]]; then
    echo ">>> jarName:[$JAR_NAME] pid:[$pidf]  process stopped success<<<"
    return 0
  fi

  if [ ! -f "$PID" ]; then
    echo -e "\npid文件不存在"
    return 0
  else
    pidf=$(cat $PID)
    #echo "$pidf"
    echo ">>> api PID = $pidf begin kill $pidf <<<"
    kill -15 $pidf
    rm -rf $PID
    sleep 5
    kill -9 $pidf
    sleep 2
    echo ">>> jarName:[$JAR_NAME] pid:[$pidf]  process stopped success<<<"
    return 0
  fi
}

#输出运行状态
status() {
  is_exist
  if [[ -z "$pid" ]]; then
    echo ""
    echo "${JAR_NAME} is not running "
    echo ""
    rm -rf $PID
  else
    echo -e "\n${JAR_NAME} is running PID is $pid "
    detail=$(ps -ef | grep $JAR_NAME | grep -v grep)
    echo -e "\n$detail\n"
  fi
}

#重启
restart() {
  stop
  start $1
}

#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
  start "$2"
  ;;
"stop")
  stop
  ;;
"status")
  status
  ;;
"restart")
  restart "$2"
  ;;
*)
  usage
  ;;
esac
exit 0

more and more

日志由应用输出到文件(方便管理)

控制台日志输出到 >/dev/null