Linux下启动Springboot服务

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Linux下通过编写Shell脚本启动Springboot

1. 背景

springboot

由于实际项目需要,需要在 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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
13天前
|
Linux 应用服务中间件 Shell
linux系统服务二!
本文详细介绍了Linux系统的启动流程,包括CentOS 7的具体启动步骤,从BIOS自检到加载内核、启动systemd程序等。同时,文章还对比了CentOS 6和CentOS 7的启动流程,分析了启动过程中的耗时情况。接着,文章讲解了Linux的运行级别及其管理命令,systemd的基本概念、优势及常用命令,并提供了自定义systemd启动文件的示例。最后,文章介绍了单用户模式和救援模式的使用方法,包括如何找回忘记的密码和修复启动故障。
35 5
linux系统服务二!
|
13天前
|
Linux 应用服务中间件 Shell
linux系统服务!!!
本文详细介绍了Linux系统(以CentOS7为例)的启动流程,包括BIOS自检、读取MBR信息、加载Grub菜单、加载内核及驱动程序、启动systemd程序加载必要文件等五个主要步骤。同时,文章还对比了CentOS6和CentOS7的启动流程图,并分析了启动流程的耗时。此外,文中还讲解了Linux的运行级别、systemd的基本概念及其优势,以及如何使用systemd管理服务。最后,文章提供了单用户模式和救援模式的实战案例,帮助读者理解如何在系统启动出现问题时进行修复。
35 3
linux系统服务!!!
|
1月前
|
JSON Java 网络架构
elasticsearch学习四:使用springboot整合 rest 进行搭建elasticsearch服务
这篇文章介绍了如何使用Spring Boot整合REST方式来搭建和操作Elasticsearch服务。
121 4
elasticsearch学习四:使用springboot整合 rest 进行搭建elasticsearch服务
|
18天前
|
Linux 数据库
Linux服务如何实现服务器重启后的服务延迟自启动?
【10月更文挑战第25天】Linux服务如何实现服务器重启后的服务延迟自启动?
80 3
|
18天前
|
关系型数据库 MySQL Linux
Linux系统如何设置自启动服务在MySQL数据库启动后执行?
【10月更文挑战第25天】Linux系统如何设置自启动服务在MySQL数据库启动后执行?
63 3
|
1月前
|
Ubuntu Linux 网络安全
Linux中服务管理问题
【10月更文挑战第4天】
25 2
|
2月前
|
缓存 前端开发 Java
springboot 的单体服务 字典参数转译
本文介绍了如何在Spring Boot项目中使用缓存来管理字典参数,并确保前后端数据一致性。首先,通过`@EnableCaching`启用缓存功能,接着创建一个自定义的字典缓存类`DicCache`。然后,通过配置类将`DicCache`添加到`cacheManager`中。此外,对字典服务进行改造,使用`@CachePut`和`@CacheEvict`注解保证数据一致性。最后,实现自定义注解`@DicSerializer`和序列化处理类`DictSerializerHandel`,用于在序列化过程中自动转换字典值。通过这种方式,可最小化代码改动并提高系统性能。
springboot 的单体服务 字典参数转译
|
1月前
|
监控 Dubbo Java
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
这篇文章详细介绍了如何将Spring Boot与Dubbo和Zookeeper整合,并通过Dubbo管理界面监控服务注册情况。
79 0
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
|
1月前
|
自然语言处理 Java Maven
elasticsearch学习二:使用springboot整合TransportClient 进行搭建elasticsearch服务
这篇博客介绍了如何使用Spring Boot整合TransportClient搭建Elasticsearch服务,包括项目创建、Maven依赖、业务代码和测试示例。
95 0
elasticsearch学习二:使用springboot整合TransportClient 进行搭建elasticsearch服务
|
1月前
|
应用服务中间件 Linux Shell
Linux 配置 Nginx 服务的详细步骤,绝对干货
Linux 配置 Nginx 服务的详细步骤,绝对干货
72 0