273 lines
6.4 KiB
Bash
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
|