美文网首页
Linux下启动Springboot服务

Linux下启动Springboot服务

作者: 孤山之王 | 来源:发表于2022-07-20 17:14 被阅读0次

    1. 背景

    由于实际项目需要,需要在 Linux 下发部署 Java Web 应用。因为此前都是通过 Weblogic来部署的,乍换一种方式,有点不使用。

    主要遇到问题有三个:

    • 启动过程有点繁琐,不够简单易用,对维护人员有一定要求,去理解每个参数的设置
    • 而且启动参数,每次重启都要输入一堆参数,不够便捷
    • 再者,重启过程需要找到进程 然后 kill 掉,再重启,耗时多

    2. 解决思路

    通过网上材料,无非通过 K8S 去管理部署应用 以及 原生 Java 方式管理,但是我们的 K8S 环境还没提供,只能暂时采用 Java 原生。

    Java 原生,参数太多,那考虑将这些参数封装成为一个 shell 脚本,以后服务的启动、停、重启或者查看状态,都是通过 一个 shell 脚本来完成。

    Shell 脚本功能就是提供应用的 启动、停、重启或者查看状态。那就是写四个方法,分别让用户选择。

    3. 实现举措

    四个核心方法,完成应用的 启动、停、重启或者查看状态。

    3.1. 核心方法

    
    function start()
    {
    
    }
    
    function stop()
    {
        
    }
    
    function restart()
    {
        
    }
    
    function status()
    {
    
    }
    
    
    

    3.2. 启动

    启动过程中指定 JVM 参数,这里提供参考 JVM_OPTS="-Dname=$SpringBoot -Duser.timezone=Asia/Shanghai -Xms1024M -Xmx1024M -XX:PermSize=256M -XX:MaxPermSize=768M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -Xloggc:$GC_LOG_PATH -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"

    设置 虚拟机内容、和 内容异常过程中Dump操作、以及设置 GC日志路径。

    3.3. 停止

    • 应用停止过程中需要判断应用当前的状态,通过 ps -ef |grep $SpringBoot |grep 'java -jar'|grep -v grep|awk '{print $2}' 检查出来应用的 PID 。

    • 通过 ps -ef |grep $SpringBoot |grep 'java -jar'|grep -v grep|awk '{print $2}' | xargs kill 来停止应用

    3.4. 重启

    结合 启动和停止,查询应用状态,服务存在的话,则 kill 应用,然后再启动应用。

    3.4.1. 查看状态

    应用停止过程中需要判断应用当前的状态,通过 ps -ef |grep $SpringBoot |grep 'java -jar'|grep -v grep|awk '{print $2}' 检查出来应用的 PID 。

    3.5. 其他

    3.5.1. 日志路径

    默认在当前应用的目录下构建 logs 日志文件夹,并按照应用名称,分目录存储。

    如应用 A,则日志文件在 logs/A/

    3.5.2. 格式化日志

    利用 function log_* 方法,定义日志的级别。

    
    LOG_LEVEL=1
    
    function log_debug(){
      content="[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 1  ] && echo -e "\033[32m"  ${content}  "\033[0m"
    }
    function log_info(){
      content="[INFO] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 2  ] && echo -e "\033[32m"  ${content} "\033[0m"
    }
    function log_warn(){
      content="[WARN] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 3  ] && echo -e "\033[33m" ${content} "\033[0m"
    }
    function log_err(){
      content="[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 4  ] && echo -e "\033[31m" ${content} "\033[0m"
    }
    function log_always(){
       content="[ALWAYS] $(date '+%Y-%m-%d %H:%M:%S') $@"
       [ $LOG_LEVEL -le 5  ] && echo -e  "\033[32m" ${content} "\033[0m"
    }
    
    

    4. 完整文件

    
    #!/bin/bash
    
    # 日志级别 debug-1, info-2, warn-3, error-4, always-5
    LOG_LEVEL=1
    
    # 调试日志
    function log_debug(){
      content="[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 1  ] && echo -e "\033[32m"  ${content}  "\033[0m"
    }
    # 信息日志
    function log_info(){
      content="[INFO] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 2  ] && echo -e "\033[32m"  ${content} "\033[0m"
    }
    # 警告日志
    function log_warn(){
      content="[WARN] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 3  ] && echo -e "\033[33m" ${content} "\033[0m"
    }
    # 错误日志
    function log_err(){
      content="[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $@"
      [ $LOG_LEVEL -le 4  ] && echo -e "\033[31m" ${content} "\033[0m"
    }
    # 一直都会打印的日志
    function log_always(){
       content="[ALWAYS] $(date '+%Y-%m-%d %H:%M:%S') $@"
       [ $LOG_LEVEL -le 5  ] && echo -e  "\033[32m" ${content} "\033[0m"
    }
    
    
    SpringBoot=$1
    
    if [ "$SpringBoot" = "" ];
    then
        log_err "Please enter the Jar application name"
        lot=$(find ./ -maxdepth 1 -type f -and -name "*.jar")
        # lot_pat=${lot#*/}
        log_err "The Optional Jar applications are as follows: $lot"
        exit 1
    fi
    
    ADATE=$(date +%Y%m%d%H%M%S)
    
    # 启动参数
    START_OPTS=$3
    
    # JVM参数
    APP_HOME=$(pwd)
    
    dirname $0|grep "^/" >/dev/null
    
    
    # 获取当前执行路径
    
    if [ $? -eq 0 ];then
         APP_HOME=$(DIR_NAME $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
    
    log_info "Current directory is $APP_HOME"
    
    ENV_PORT=${START_OPTS#*=}
    
    ENV_DIR="$APP_HOME/logs"
    
    
    if [ "$ENV_PORT" = "" ]; then
        log_info "Application Port is Null"
        log_info "$ENV_DIR"
        if [ ! -d "$ENV_DIR"  ];then
            mkdir -p $ENV_DIR
        fi
    
    else
        log_info "Application Port is $ENV_PORT"
        ENV_DIR="$ENV_DIR/$ENV_PORT"
        log_info "$ENV_DIR"
        if [ ! -d "$ENV_DIR"  ];then
            mkdir -p $ENV_DIR
        fi
    fi
    
    log_warn " Construct log folder $ENV_DIR"
    
    pid=0
    
    Purpose=$2
    
    # 当没有输入具体,操作,默认为 START ,此时需要用户二次确认,输入 Y|y|YES|Yes 同意操作
    # 或者 n|N|NO|no ,不同意重启,直接退出
    if [ "$Purpose" = "" ];
        then
            log_err "Operation Name Not Entered : The Default Action Is START !"
            read -p  "Are You Sure?[y/n]:"  sure
            case  $sure  in
                y|Y|Yes|YES)  
                    log_warn "You Enter $a"
                    log_warn "Prepare to restart the app: $SpringBoot"
                    Purpose="start"
                    ;;
                n|N|NO|no)
                    echo "you enter $a"
                    log_warn "Ready To Exit Startup: $SpringBoot"
                    exit 1
                    ;;
                *)
                    echo "error";;
            esac
    fi
    
    
    log_debug "##############################"
    
    log_debug "Java environment variable information"
    
    LOG_PATH=$ENV_DIR/$SpringBoot-$ADATE.log
    GC_LOG_PATH=$ENV_DIR/gc-$SpringBoot-$ADATE.log
    
    VSpringBoot=${SpringBoot%%.*}
    
    LOG_DEBUG_PATH=$ENV_DIR/$VSpringBoot/debug.log
    
    log_debug "LOG_DEBUG_PATH is $LOG_DEBUG_PATH"
    
    
    log_debug "$(java -version)"
    log_debug "Startup log  $LOG_PATH"
    
    log_debug "Startup gc log  $GC_LOG_PATH"
    
    JVM_OPTS="-Dname=$SpringBoot -Duser.timezone=Asia/Shanghai -Xms1024M -Xmx1024M -XX:PermSize=256M -XX:MaxPermSize=768M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -Xloggc:$GC_LOG_PATH -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
    
    log_debug "$JVM_OPTS $GC_LOG_PATH"
    
    # 启动项目,如果项目已经启动过,则先 kill 掉原先项目,再启动
    function start()
    {
        # 检查项目的进程是否存在
        checkPid
        # 
        if [ $pid -ne "0" ]; then
            log_info "Application  $SpringBoot Running... PID:$pid ,Please Stop It"
            # echo -e "\033[31m Application  $SpringBoot Running... PID:$pid ,Please Stop It  \033[0m"
            # Kill the current Process
            killPid
            log_info ".............."
            startFun
        else
            log_info ".............."
            startFun
            log_info ".............."
        fi
    }
    
    
    checkPid()
    {
        pid=$(ps -ef |grep $SpringBoot |grep 'java -jar'|grep -v grep|awk '{print $2}')
        # `ps -aux | grep $SpringBoot | grep 'java -jar'|grep -v grep | awk '{print $2}' | xargs kill`
    }
    
    killPid()
    {
        log_err "Application PID:$pid is being stopped, Please wait for a while, or fish"
        # echo -e "\033[31m Application PID:$pid is being stopped, Please wait for a while, or fish  \033[0m"
        $(ps -ef |grep $SpringBoot |grep 'java -jar'|grep -v grep|awk '{print $2}' | xargs kill)
        tail -n 10 $LOG_DEBUG_PATH
        sleep 10s
    }
    
    startFun()
    {
        log_debug "Begin Start $SpringBoot ..."
        # echo -e "\033[32m Begin Start $SpringBoot ...  \033[0m"
        $(java -jar $JVM_OPTS $SpringBoot $START_OPTS > $LOG_PATH 2>&1 &)
        # nohup java -jar $JVM_OPTS $SpringBoot --spring.config.location=file:./application.yml $START_OPTS > $LOG_PATH 2>&1 &
        log_debug "$SpringBoot SUCCESS..."
        #echo -e "\033[32m $SpringBoot SUCCESS...  \033[0m"
        sleep 10s
        tail -n 300 $LOG_PATH
    
    }
    
    function stop()
    {
        checkPid
        log_info "Begin Stop Application $SpringBoot"
        # echo "Begin Stop Application $SpringBoot"
        if [ "$pid" -ne "0" ]; then
            log_err "$SpringBoot stop..."
            # echo "$SpringBoot stop..."
            killPid
        else
            log_info "$SpringBoot not running!"
            # echo "$SpringBoot not running!"
        fi
    
    }
    
    function restart()
    {
        # stop
        sleep 3s
        start
    }
    
    function status()
    {
        checkPid
        if [ "$pid" -ne "0" ]; then
            log_info "$SpringBoot not running!"
            #echo "$SpringBoot not running!"    
        else
            log_info "$SpringBoot is running... PID:$pid"
            # echo "$SpringBoot is running... PID:$pid"
        fi
    }
    
    case $Purpose in
        start) start;;
        stop) stop;;
        restart) restart;;
        status) status;;
        *) log_info "require start|stop|restart|status"  ;;
    
    esac
    
    
    

    5. 使用

    sh restart.sh $1 $2 $3

    • $1 : SpringBoot 应用名.jar 必选
    • $2 :操作内容,可空,为空默认为 restart
    • $3 : 其他参数,可空

    样例如下:

    
    sh restart.sh cia-codegen.jar
    
    

    6. 效果图

    20220720165706.png

    相关文章

      网友评论

          本文标题:Linux下启动Springboot服务

          本文链接:https://www.haomeiwen.com/subject/icqyirtx.html