319 lines
9.5 KiB
Bash
319 lines
9.5 KiB
Bash
#!/bin/bash
|
|
# 通用启动脚本, 如果需要自定义, 可在 `${project.basedir}/src/main/resources/bin` 目录下创建同名文件, 框架在打包时将会使用自定义脚本.
|
|
# ____
|
|
# /\ _`\ __ /'\_/`\
|
|
# \ \ \L\ \ __ __ ___ ___ /\_\ ___ __ /\ \ __ ___
|
|
# \ \ , / /\ \/\ \ /' _ `\ /' _ `\ \/\ \ /' _ `\ /'_ `\ \ \ \__\ \ /'__`\ /' _ `\
|
|
# \ \ \\ \ \ \ \_\ \/\ \/\ \ /\ \/\ \ \ \ \ /\ \/\ \ /\ \L\ \ \ \ \_/\ \ /\ \L\.\_ /\ \/\ \
|
|
# \ \_\ \_\ \ \____/\ \_\ \_\\ \_\ \_\ \ \_\\ \_\ \_\\ \____ \ \ \_\\ \_\\ \__/.\_\\ \_\ \_\
|
|
# \/_/\/ / \/___/ \/_/\/_/ \/_/\/_/ \/_/ \/_/\/_/ \/___L\ \ \/_/ \/_/ \/__/\/_/ \/_/\/_/
|
|
# /\____/
|
|
#
|
|
# :: FKH Boot Startup Script ::
|
|
|
|
readonly TURN=0 && readonly FALSE=1
|
|
|
|
# ANSI Colors
|
|
echo_red() { echo $'\e[0;31m'"$1"$'\e[0m'; }
|
|
echo_green() { echo $'\e[0;32m'"$1"$'\e[0m'; }
|
|
echo_yellow() { echo $'\e[0;33m'"$1"$'\e[0m'; }
|
|
|
|
# info级别的日志
|
|
log_info() {
|
|
echo -e "[$(date +'%Y-%m-%dT%H:%M:%S%z')][$$]: \033[32m [info] \033[0m $*" >&2
|
|
}
|
|
|
|
# error级别的日志
|
|
log_error() {
|
|
echo -e "[$(date +'%Y-%m-%dT%H:%M:%S%z')][$$]: \033[31m [error] \033[0m $*" >&2
|
|
}
|
|
|
|
# 初始化 debug 参数
|
|
function init_debug() {
|
|
if [[ "${DEBUG_PORD}" != "-1" ]]; then
|
|
expr "${DEBUG_PORD}" "+" 10 &>/dev/null
|
|
if [[ $? -eq 0 ]]; then
|
|
DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$DEBUG_PORD -Dloader.debug"
|
|
echo_yellow "开启 DEBUG 模式: DEBUG_OPTS=$DEBUG_OPTS"
|
|
else
|
|
echo_red "请输入正确的端口号"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
}
|
|
|
|
# 获取应用部署路径
|
|
function prepare() {
|
|
|
|
APP_HOME=$(pwd)
|
|
dirname $0 | grep "^/" >/dev/null
|
|
if [[ $? -eq 0 ]]; then
|
|
APP_HOME=$(dirname $0)
|
|
else
|
|
dirname $0 | grep "^\." >/dev/null
|
|
retval=$?
|
|
if [[ ${retval} -eq 0 ]]; then
|
|
APP_HOME=$(dirname $0 | sed "s#^.#$APP_HOME#")
|
|
else
|
|
APP_HOME=$(dirname $0 | sed "s#^#$APP_HOME/#")
|
|
fi
|
|
fi
|
|
|
|
# 默认使用打包后的 artifactId 作为应用名
|
|
DEPLOY_DIR=$(dirname "$APP_HOME")
|
|
# 从 build-info.properties 读取应用名
|
|
APP_NAME=$(awk -F '=' '{if($1~/build.project.name/) printf $2}' "${DEPLOY_DIR}"/config/build-info.properties)
|
|
JAR_FILE=${DEPLOY_DIR}/${APP_NAME}.jar
|
|
GC_LOG=${LOG_PATH}/${ENV}/${APP_NAME}/gc.log
|
|
}
|
|
|
|
# 获取 pid
|
|
function check_pid() {
|
|
PID=$(ps -ef | grep -v grep | grep "${APP_NAME}@${ENV}" | awk '{print $2}')
|
|
}
|
|
|
|
# 创建日志目录和文件
|
|
function mkdir_log_file() {
|
|
FINAL_LOG_PATH="${LOG_PATH}/${ENV}/${APP_NAME}"
|
|
mkdir -p ${FINAL_LOG_PATH}
|
|
if [[ ! -f "${FINAL_LOG_PATH}/${LOG_NAME}" ]]; then
|
|
touch "${FINAL_LOG_PATH}/${LOG_NAME}"
|
|
fi
|
|
}
|
|
|
|
# 设置环境, 与应用配置 bootstrap.yml 的 ${FKH_NAME_SPACE} 对应, 此处设置的变量会被 spring 在启动时替换
|
|
# 使用 -DIDENTIFY 来区分应用 (由于服务器资源有限, 一台服务器可能会部署同一个应用, 只是环境不同而已)
|
|
# 重写 fkh.logging.file.path 配置
|
|
function running() {
|
|
# 设置 JVM 参数
|
|
local jvm_opts="-Dname=${APP_NAME} -Xloggc:${GC_LOG} -XX:ErrorFile=${DEPLOY_DIR}/app_error_%p.log -XX:HeapDumpPath=${DEPLOY_DIR}/app_error.hprof"
|
|
|
|
jvm_opts="${jvm_opts} #{jvmOptions}"
|
|
|
|
echo -e "JVM 启动参数: ${jvm_opts}"
|
|
|
|
nohup ${javaexe} -jar \
|
|
${jvm_opts} \
|
|
-Dloader.home=${DEPLOY_DIR}/ \
|
|
-Dloader.path=lib/ \
|
|
-DAPP_NAME=${APP_NAME} \
|
|
-DIDENTIFY=${APP_NAME}@${ENV} \
|
|
-DFKH_NAME_SPACE=fkh-${ENV} \
|
|
-Ddeploy.path=${DEPLOY_DIR} \
|
|
-Dstart.type=shell \
|
|
-Dconfig.path=${DEPLOY_DIR}/config/ \
|
|
-Dfkh.logging.file.path=${LOG_PATH}/${ENV} \
|
|
-Dfkh.logging.file.name=${LOG_NAME} \
|
|
-Djar.file=${JAR_FILE} \
|
|
${DEBUG_OPTS} \
|
|
${JAR_FILE} \
|
|
--slot.root=${DEPLOY_DIR}/ \
|
|
--slot.path=patch/ \
|
|
--slot.path=plugin/ \
|
|
--spring.profiles.active=${ENV} \
|
|
--spring.config.location=${DEPLOY_DIR}/config/ >${FINAL_LOG_PATH}/${LOG_NAME} 2>&1 &
|
|
|
|
echo_green "--------------------------------------"
|
|
echo_green " starting ${APP_NAME} "
|
|
echo_green "--------------------------------------"
|
|
}
|
|
|
|
# 输出所有参数
|
|
function show_info() {
|
|
echo -e "\033[31m ENV: ${ENV} \033[0m"
|
|
echo -e "\033[32m FUNC: ${FUNC} \033[0m"
|
|
echo -e "\033[33m DEBUG_PORD: ${DEBUG_PORD} \033[0m"
|
|
echo -e "\033[34m SHOW_LOG: ${SHOW_LOG} \033[0m"
|
|
echo -e "\033[35m DEBUG_OPTS: ${DEBUG_OPTS} \033[0m"
|
|
echo -e "\033[36m APP_NAME: ${APP_NAME} \033[0m"
|
|
echo -e "\033[31m DEPLOY_DIR: ${DEPLOY_DIR} \033[0m"
|
|
echo -e "\033[32m JAR_FILE: ${JAR_FILE} \033[0m"
|
|
echo -e "\033[34m GC_LOG: ${GC_LOG} \033[0m"
|
|
echo -e "\033[35m FINAL_LOG_PATH: ${FINAL_LOG_PATH} \033[0m"
|
|
echo -e "\033[36m JAVA_HOME: ${JAVA_HOME} \033[0m"
|
|
echo -e "\033[32m IDENTIFY: ${APP_NAME}@${ENV} \033[0m"
|
|
echo -e "\033[33m FKH_NAME_SPACE: fkh-${ENV} \033[0m"
|
|
}
|
|
|
|
# 启动应用 (-s env)
|
|
function start() {
|
|
check_pid
|
|
|
|
if [[ -z "${PID}" ]]; then
|
|
mkdir_log_file
|
|
running
|
|
|
|
echo_green "日志路径: ${FINAL_LOG_PATH}/${LOG_NAME}"
|
|
echo -e "\n"
|
|
|
|
if [[ ${SHOW_INFO} = "on" ]]; then
|
|
show_info
|
|
fi
|
|
|
|
if [[ ${SHOW_LOG} = "on" ]]; then
|
|
tail -100f ${FINAL_LOG_PATH}/${LOG_NAME} | perl -pe 's/(WARN)|(ERROR)/\e[1;33m$1\e[0m\e[1;31m$2\e[0m/g'
|
|
fi
|
|
|
|
else
|
|
echo_green "${APP_NAME}@${ENV} is running. [pid: ${PID}]"
|
|
fi
|
|
}
|
|
|
|
# 关闭应用 (-S env)
|
|
function stop() {
|
|
check_pid
|
|
if [[ ! -n "${PID}" ]]; then
|
|
echo_red "The ${APP_NAME}@${ENV} does not started!"
|
|
else
|
|
echo_red "shudown the ${APP_NAME}@${ENV}"
|
|
kill ${PID} >/dev/null 2>&1
|
|
COUNT=0
|
|
KILL_COUNT=0
|
|
# COUNT 小于 1
|
|
while [[ ${COUNT} -lt 1 ]]; do
|
|
echo -e ".\c"
|
|
KILL_COUNT=$((${KILL_COUNT} + 1))
|
|
if [[ ${KILL_COUNT} -gt 5 ]]; then
|
|
echo -e "\n"
|
|
kill -9 ${PID} >/dev/null 2>&1
|
|
fi
|
|
# 检查是否干掉 app
|
|
PID_EXIST=$(ps -ef | grep -v grep | grep "${APP_NAME}@${ENV}" | awk '{print $2}')
|
|
# 如果为空, 则退出循环
|
|
if [[ ! -n "${PID_EXIST}" ]]; then
|
|
COUNT=1
|
|
fi
|
|
sleep 1s
|
|
done
|
|
echo
|
|
echo_green "${APP_NAME}@${ENV} shudown success. [pid = ${PID}]"
|
|
fi
|
|
}
|
|
|
|
# 重启应用 (-r env)
|
|
function restart() {
|
|
stop
|
|
sleep 1s
|
|
start
|
|
}
|
|
|
|
# 查看应用状态 (-c env)
|
|
function status() {
|
|
check_pid
|
|
if [[ ! -n "${PID}" ]]; then
|
|
echo_green "${APP_NAME}@${ENV} not running"
|
|
else
|
|
echo_red "${APP_NAME}@${ENV} running. [pid: ${PID}]"
|
|
fi
|
|
}
|
|
|
|
JAVA_HOME=$(echo ${JAVA_HOME})
|
|
|
|
if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
|
|
javaexe="$JAVA_HOME/bin/java"
|
|
elif type -p java >/dev/null 2>&1; then
|
|
javaexe=$(type -p java)
|
|
elif [[ -x "/usr/bin/java" ]]; then
|
|
javaexe="/usr/bin/java"
|
|
else
|
|
# 测试, 预演 jdk 的绝对路径
|
|
javaexe="$(find /opt -name 'jdk1.8*')/bin/java"
|
|
fi
|
|
|
|
echo "JAVA_HOME: ${javaexe}"
|
|
|
|
# 默认 dev 环境
|
|
ENV="dev"
|
|
# 默认为启动
|
|
FUNC="start"
|
|
# 默认 debug 关闭
|
|
DEBUG_PORD="-1"
|
|
# 默认启动后 tail 日志
|
|
SHOW_LOG="off"
|
|
SHOW_INFO="off"
|
|
# shell 启动时使用默认的日志路径
|
|
LOG_PATH="/mnt/syslogs/v5"
|
|
LOG_NAME="all.log"
|
|
# 最终的日志路径
|
|
FINAL_LOG_PATH=""
|
|
# 自定义参数, 先设置变量
|
|
while getopts "s:r:S:d:c:h:tTiH" opt; do
|
|
case ${opt} in
|
|
# 启动应用, 跟环境变量
|
|
s)
|
|
ENV=${OPTARG}
|
|
FUNC="start"
|
|
;;
|
|
# 重启应用 跟环境变量
|
|
r)
|
|
ENV=${OPTARG}
|
|
FUNC="restart"
|
|
;;
|
|
c)
|
|
ENV=${OPTARG}
|
|
FUNC="status"
|
|
;;
|
|
# 关闭应用
|
|
S)
|
|
ENV=${OPTARG}
|
|
FUNC="stop"
|
|
;;
|
|
# 使用 debug 模式 跟监听端口
|
|
d)
|
|
DEBUG_PORD=${OPTARG}
|
|
;;
|
|
t)
|
|
SHOW_LOG="on"
|
|
;;
|
|
T)
|
|
SHOW_LOG="on"
|
|
LOG_PATH=$(mktemp -d)
|
|
;;
|
|
h)
|
|
ENV=${OPTARG}
|
|
FUNC="helper"
|
|
;;
|
|
i)
|
|
SHOW_INFO="on"
|
|
;;
|
|
H)
|
|
echo -e "\033[0;36m
|
|
1. 在任何目录下执行此脚本都可以.
|
|
2. 最简单的命令就是不输入任何参数 (./server.sh 即以${ENV}环境启动应用).
|
|
3. 输入 -s , -r 和 -S 参数, 后面必须跟环境变量 (dev/test/prod);
|
|
4. -d, -t, -T -i 参数不能单独存在, 且必须跟在 -s 或者 -r 后面;
|
|
5. -h 参数不需要手动调用, 是程序自动调用, 用于启动 helper 进程来对主应用进行重启操作.\033[0m \033[0;34m
|
|
|
|
-s:启动应用 exp: bin/server.sh (默认以 ${ENV} 环境启动应用, 不需要输入任何参数)
|
|
-s:启动应用 exp: bin/server.sh -s test (以 test 环境启动应用)
|
|
-r:重启应用 exp: bin/server.sh -r prod (以 prod 环境重启应用)
|
|
-S:关闭应用 exp: bin/server.sh -S test (关闭应用)
|
|
-c:查看状态 exp: bin/server.sh -c test (查看应用状态)
|
|
-t:查看日志 exp: bin/server.sh -s dev (启动时自动 tail 全量日志)
|
|
-T:输出日志到临时文件\texp: bin/server.sh -s dev -T\t\t(启动时自动 tail 全量日志, 主要用于部署测试用, 日志会写入到临时文件, 生产环境不要使用)
|
|
-d:debug 模式\t\texp: bin/server.sh -s dev -d 5005\t(以 dev 环境启动应用, 端口默认为 5005, 并且开启 debug 模式, 用于 idea 远程调试)
|
|
-i:输出所有参数信息\texp: bin/server.sh -s dev -i\t\t(启动时输出参数信息)
|
|
\033[0m"
|
|
exit 1
|
|
;;
|
|
\?)
|
|
echo_red "参数列表错误 使用 -H 查看帮助"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# 1. 处理 debug 参数
|
|
init_debug
|
|
# 2. 处理部署包路径
|
|
prepare
|
|
# 3. 通过 func 来执行具体方法
|
|
case ${FUNC} in
|
|
start) start ;;
|
|
stop) stop ;;
|
|
restart) restart ;;
|
|
status) status ;;
|
|
*) echo_red "参数错误 require -s|-r|-S|-c" ;;
|
|
esac
|