#!/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