erp-java/services/scheduled-task-service/deploy/shell/start.sh

273 lines
6.4 KiB
Bash

#!/bin/bash
# =========================================
# 定时任务调度服务 - 启动脚本
# =========================================
set -e
APP_NAME="scheduled-task-service"
APP_HOME="/opt/erp/${APP_NAME}"
LOG_HOME="/var/log/erp/${APP_NAME}"
CONFIG_HOME="/etc/erp/${APP_NAME}"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
warn() {
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
error() {
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
# 检查Java
check_java() {
if ! command -v java &> /dev/null; then
error "Java not found. Please install JDK 17+"
exit 1
fi
JAVA_VERSION=$(java -version 2>&1 | head -n 1 | cut -d'"' -f2 | cut -d'.' -f1)
if [ "$JAVA_VERSION" -lt 17 ]; then
error "Java 17+ required, current version: $JAVA_VERSION"
exit 1
fi
log "Java version check passed"
}
# 创建目录
create_dirs() {
log "Creating directories..."
mkdir -p ${APP_HOME}
mkdir -p ${LOG_HOME}
mkdir -p ${CONFIG_HOME}
}
# 备份配置
backup_config() {
if [ -f "${CONFIG_HOME}/application.yml" ]; then
BACKUP_FILE="${CONFIG_HOME}/application.yml.bak.$(date +%Y%m%d%H%M%S)"
warn "Backing up config to: ${BACKUP_FILE}"
cp ${CONFIG_HOME}/application.yml ${BACKUP_FILE}
fi
}
# 启动应用
start_app() {
log "Starting ${APP_NAME}..."
cd ${APP_HOME}
JAVA_OPTS="-Xms512m -Xmx1024m"
JAVA_OPTS="${JAVA_OPTS} -XX:+UseG1GC"
JAVA_OPTS="${JAVA_OPTS} -XX:+HeapDumpOnOutOfMemoryError"
JAVA_OPTS="${JAVA_OPTS} -XX:HeapDumpPath=${LOG_HOME}/heapdump.hprof"
JAVA_OPTS="${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom"
JAVA_OPTS="${JAVA_OPTS} -Dspring.config.additional-location=${CONFIG_HOME}/"
JAVA_OPTS="${JAVA_OPTS} -Dlogging.file.path=${LOG_HOME}"
nohup java ${JAVA_OPTS} -jar ${APP_HOME}/${APP_NAME}.jar \
--spring.config.additional-location=${CONFIG_HOME}/ \
>> ${LOG_HOME}/stdout.log 2>&1 &
APP_PID=$!
echo ${APP_PID} > ${APP_HOME}/app.pid
log "${APP_NAME} started with PID: ${APP_PID}"
# 等待应用启动
wait_for_app
}
# 等待应用启动完成
wait_for_app() {
log "Waiting for application to start..."
MAX_WAIT=120
COUNTER=0
while [ $COUNTER -lt $MAX_WAIT ]; do
if curl -sf http://localhost:8088/actuator/health > /dev/null 2>&1; then
log "${APP_NAME} is ready!"
return 0
fi
if ! ps -p $APP_PID > /dev/null 2>&1; then
error "Application process died!"
tail -100 ${LOG_HOME}/stdout.log
exit 1
fi
sleep 2
COUNTER=$((COUNTER + 2))
echo -n "."
done
error "Application failed to start within ${MAX_WAIT} seconds"
tail -100 ${LOG_HOME}/stdout.log
exit 1
}
# 停止应用
stop_app() {
log "Stopping ${APP_NAME}..."
if [ -f ${APP_HOME}/app.pid ]; then
PID=$(cat ${APP_HOME}/app.pid)
if ps -p $PID > /dev/null 2>&1; then
kill -15 $PID
# 等待最多30秒
for i in {1..30}; do
if ! ps -p $PID > /dev/null 2>&1; then
log "${APP_NAME} stopped"
rm -f ${APP_HOME}/app.pid
return 0
fi
sleep 1
done
# 强制kill
warn "Force killing ${APP_NAME}..."
kill -9 $PID 2>/dev/null || true
rm -f ${APP_HOME}/app.pid
else
warn "Process $PID not found"
rm -f ${APP_HOME}/app.pid
fi
else
warn "PID file not found"
# 尝试查找进程
PID=$(pgrep -f ${APP_NAME})
if [ -n "$PID" ]; then
warn "Found process: $PID, killing..."
kill -15 $PID 2>/dev/null || true
sleep 5
pkill -9 -f ${APP_NAME} 2>/dev/null || true
fi
fi
}
# 查看状态
status() {
if [ -f ${APP_HOME}/app.pid ]; then
PID=$(cat ${APP_HOME}/app.pid)
if ps -p $PID > /dev/null 2>&1; then
log "${APP_NAME} is running (PID: $PID)"
if curl -sf http://localhost:8088/actuator/health > /dev/null 2>&1; then
log "Health check: OK"
else
warn "Health check: FAILED"
fi
else
warn "${APP_NAME} is not running (stale PID file)"
fi
else
PID=$(pgrep -f ${APP_NAME})
if [ -n "$PID" ]; then
log "${APP_NAME} is running (PID: $PID)"
else
warn "${APP_NAME} is not running"
fi
fi
}
# 查看日志
logs() {
tail -f ${LOG_HOME}/stdout.log
}
# 构建项目
build() {
log "Building ${APP_NAME}..."
cd $(dirname $(dirname $(readlink -f $0)))
if [ -f "pom.xml" ]; then
./mvnw clean package -DskipTests
else
error "pom.xml not found"
exit 1
fi
log "Build completed"
}
# 打包Docker镜像
docker_build() {
log "Building Docker image..."
cd ${APP_HOME}/..
docker build -t ${APP_NAME}:1.0.0 -f deploy/docker/Dockerfile .
log "Docker image built: ${APP_NAME}:1.0.0"
}
# 主菜单
usage() {
echo ""
echo "========================================="
echo " 定时任务调度服务管理脚本"
echo "========================================="
echo ""
echo "Usage: $0 {start|stop|restart|status|logs|build|docker_build}"
echo ""
echo "Commands:"
echo " start - Start the application"
echo " stop - Stop the application"
echo " restart - Restart the application"
echo " status - Check application status"
echo " logs - View application logs"
echo " build - Build the application"
echo " docker_build - Build Docker image"
echo ""
}
# 主入口
case "$1" in
start)
check_java
create_dirs
backup_config
start_app
;;
stop)
stop_app
;;
restart)
stop_app
sleep 5
start_app
;;
status)
status
;;
logs)
logs
;;
build)
build
;;
docker_build)
docker_build
;;
*)
usage
exit 1
;;
esac
exit 0