推广

运行 Java SpringBoot 的 Linux 脚本 run.sh

iseeyu3年前 (2024-02-22)推广136

1. 用法

添加文件的执行权限

# 首次执行第一次即可
chmod +x run.sh

重启并清空日志

查看状态

启动

停止

2. 说明

# 赋予执行权限(初始化执行一次)
chmod +x run.sh 
# 启动应用程序
sh run.sh start
# 停止应用程序
sh run.sh stop
# 查看应用程序
# sh run.sh status
# 重启应用程序
sh run.sh restart c  # 加 c 删除历史日志文件
# 查看应用日志
sh run.sh logs

3. 源码(run.sh)

#!/bin/bash
#
# ================================================ 说明 start ================================================
# 1. 赋予执行权限: chmod +x run.sh
# 2. 启动应用程序: sh run.sh start
# 3. 停止应用程序: sh run.sh stop
# 4. 查看应用程序: sh run.sh status
# 5. 重启应用程序: sh run.sh restart c # 加 c 删除历史日志文件
# 6. 查看应用日志: sh run.sh logs
# ================================================ 说明 end   ================================================
#
# ================================================ 作者 start ================================================
# @author: houyu
# @date: 2021-08-19
# @mail: for.houyu@qq.com(272694308@qq.com)
# @blog: https://www.ihouyu.cn
# @csdn: https://blog.csdn.net/JinglongSource
# ================================================ 作者 end   ================================================
# 刷新环境变量
source /etc/profile
# ================================================ 参数 start ================================================
# ------ Java 路径, 可以是 JAVA_HOME 也可以 Java 可执行文件路径, 默认使用环境变量的 JAVA_HOME
#JAVA="/usr/local/java/jdk1.8.0_281/bin/java"
#JAVA="/usr/local/java/jdk1.8.0_281"
JAVA="${JAVA_HOME}"
# ------ 文件路径
DIR_PATH=`cd $(dirname $0); pwd`
# ------ 服务文件名(默认使用目录下最新的.jar或者.war文件)
SERVER_FILE_NAME=`ls -t ${DIR_PATH} | egrep '\.jar|\.war' | head -1`
# ------ Java 参数
JAVA_OPT="${JAVA_OPT} -Duser.timezone=Asia/Shanghai"
JAVA_OPT="${JAVA_OPT} -Xms128m -Xmx128m"
# ------ Spring 参数
SPRING_OPT="${SPRING_OPT} --spring.profiles.active=prod"
# ------ 控制台文件
#CONSOLE_FILE="/dev/null"
CONSOLE_FILE="${DIR_PATH}/logs/console.log"
# ------ 停止时等待超时的秒数
STOP_TIMEOUT=60
#
# ================================================ 参数 end   ================================================
#
# ================================================ 方法 start ================================================
#
# 服务PID
_SERVER_PID=0
# 服务端口
_SERVER_PORT=0
# 日志目录
_LOG_PATH="${DIR_PATH}/logs"
# 输入的第二个参数
_P2=$2
#
# =======================================
# 解析服务的 pid
# =======================================
resolve_server_pid() {
    _SERVER_PID=0
    if [ -f "${_LOG_PATH}/server.pid" ]; then
        # pid 文件存在则读取文件
        _SERVER_PID=$(cat "${_LOG_PATH}/server.pid")
        # 判断是否真的存在这个 pid
        if test $(ps -ef | awk '{print $2}' | grep -w ${_SERVER_PID} | wc -l) -eq 0; then
            # 没有找到文件记录的 pid, 删除这个文件
            rm -rf ${_LOG_PATH}/server.pid
            sleep 0.2
            _SERVER_PID=0
            # 重新解析服务的 pid
            #resolve_server_pid
        fi
    #else
    #    # pid文件不存在则尝试根据应用程序的名称获取pid
    #    if test $(pgrep -f ${SERVER_FILE_NAME} | wc -l) -gt 0; then
    #        # 说明应用程序正在跑, 使用第一个pid
    #        _SERVER_PID=$(pgrep -f ${SERVER_FILE_NAME} | head -1)
    #    else
    #        _SERVER_PID=0
    #    fi
    fi
}
#
# =======================================
# 解析服务的端口
# =======================================
retry_resolve_server_port() {
    _SERVER_PORT=0
    # 解析服务的 pid
    resolve_server_pid
    # 检测5分钟(300秒)
    for(( i=0; i<=300; i++ )); do
        # 判断 pid 是否存在
        if test $(ps -ef | awk '{print $2}' | grep -w ${_SERVER_PID} | wc -l) -eq 0; then
            rm -rf ${_LOG_PATH}/server.pid
            _SERVER_PID=0
            break
        fi
        # 判断 pid 的 port 是否绑定
        if test $(netstat -tulnp | grep "${_SERVER_PID}/" | wc -l) -gt 0; then
            _SERVER_PORT=$(netstat -tulnp | grep "${_SERVER_PID}/" | head -1 | awk '{print $4}' | awk -F ":" '{print $NF}')
            break
        fi
        [[ $i%5 -eq 0 ]] && echo "--- Observing server port using ${i}s"
        sleep 1
    done
}
#
# =======================================
# 启动
# =======================================
start() {
    echo "----------------------------------------------------------------------------- Start [0] ------"
    # 解析服务的 pid
    resolve_server_pid
    if [ "${_SERVER_PID}" -ne 0 ]; then
        # 如果 _SERVER_PID != 0, 那就说明应用程序在运行,不进行启动
        echo "--- Do not start, ${SERVER_FILE_NAME} already started! [ SERVER_PID = ${_SERVER_PID} ]"
        echo "----------------------------------------------------------------------------- Start [1] ------"
        return
    fi
    #
    echo "--- Starting ${SERVER_FILE_NAME} ..."
    # 如果 JAVA 是一个目录,则加上/bin/java
    [ -d "${JAVA}" ] && JAVA="${JAVA}/bin/java"
    # 如果 JAVA 不是一个存在的文件, 则尝试使用默认的java
    [ ! -e "$JAVA" ] && JAVA=`which java`
    # 最终 Java 不是一个存在的文件, 则清空
    [ ! -e "$JAVA" ] && unset JAVA
    if [ -z "${JAVA}" ]; then
        echo -e "\033[31mPlease set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better!\033[0m"
        exit 1
    fi
    # 判断是否需要删除日志文件
    if [[ "$_P2" == "c" ]]; then
        # 如果第二个参数是c, 删除日志文件
        echo -e "--- \033[33mDeleting ${SERVER_FILE_NAME} log file(${DIR_PATH}/logs/*)\033[0m"
        rm -rf ${DIR_PATH}/logs/*
    fi
    # 检查日志目录
    test -d ${DIR_PATH}/logs/ || mkdir -p ${DIR_PATH}/logs/
    # 执行脚本
    # nohup java -Xmx128m -jar /home/app/server.jar --spring.profiles.active=prod >> /home/app/logs/console.log 2>&1 & echo $! > /home/app/logs/server.pid
    #
    # 运行的参数
    RUN_OPT="${JAVA_OPT} -jar"
    RUN_OPT="${RUN_OPT} ${DIR_PATH}/${SERVER_FILE_NAME}"
    [ -n "${SPRING_OPT}" ] && RUN_OPT="${RUN_OPT} ${SPRING_OPT}"
    #
    echo "--- $JAVA ${RUN_OPT}"
    echo "$JAVA ${RUN_OPT}" > ${CONSOLE_FILE}
    nohup $JAVA ${RUN_OPT} >> ${CONSOLE_FILE} 2>&1 & echo $! > ${_LOG_PATH}/server.pid
    #
    echo "--- ${SERVER_FILE_NAME} is running"
    echo -e "--- You can check the log file \033[36m${CONSOLE_FILE}\033[0m or execute the command on the next line"
    echo -e "--- \033[40;37mtail -f -n 300 ${CONSOLE_FILE}\033[0m"
    # 睡眠1秒
    sleep 1
    # 解析服务的 pid
    resolve_server_pid
    # 判断应用程序是否成功跑起来
    if [ "${_SERVER_PID}" -eq 0 ]; then
        echo -e "--- \033[31mStart failure ${SERVER_FILE_NAME}\033[0m"
    else
        if [ -n "${SPRING_OPT}" ]; then
            # 如果是 Spring 项目, 需要观察端口是否成功绑定
            retry_resolve_server_port
            # 
            if [ "${_SERVER_PORT}" -eq 0 ]; then
                echo -e "--- \033[31mStart failure ${SERVER_FILE_NAME}\033[0m"
            else
                _SERVER_PORT_TEXT=`netstat -tulnp | grep "${_SERVER_PID}/" | awk 'BEGIN{ORS=" "}{print $4}'`
                echo -e "--- \033[32mStart successfully ${SERVER_FILE_NAME} [ SERVER_PID = ${_SERVER_PID}, SERVER_PORT = ${_SERVER_PORT_TEXT}]\033[0m"
            fi
        else
            echo -e "--- \033[32mStart successfully ${SERVER_FILE_NAME} [ SERVER_PID = ${_SERVER_PID}, \033[0m\033[33mSERVER_PORT = unknown \033[0m\033[32m]\033[0m"
        fi
    fi
    echo "----------------------------------------------------------------------------- Start [1] ------"
}
#
# =======================================
# 停止
# =======================================
stop() {
    echo "----------------------------------------------------------------------------- Stop  [0] ------"
    # 解析服务的 pid
    resolve_server_pid
    if [ "${_SERVER_PID}" -eq 0 ]; then
        # _SERVER_PID = 0, 那就说明应用程序没有在运行
        echo "--- Stopped ${SERVER_FILE_NAME}"
        echo "----------------------------------------------------------------------------- Stop  [1] ------"
        return
    fi
    echo "--- Graceful Stopping ${SERVER_FILE_NAME} ..."
    # 进行优雅停机
    kill -15 ${_SERVER_PID}
    # 当前等待秒数
    _wait_seconds=0
    #
    while true; do
        if test $(ps -ef | awk '{print $2}' | grep -w ${_SERVER_PID} | wc -l) -eq 0; then
            echo "--- Stopped ${SERVER_FILE_NAME}"
            break
        fi
        if [ "${_wait_seconds}" -ge "${STOP_TIMEOUT}" ]; then
            # 强制终止进程
            echo -e "--- \033[31mWait timeout(${_wait_seconds}s), forced shutdown [kill -9 ${SERVER_FILE_NAME}].\033[0m"
            sudo kill -9 ${_SERVER_PID}
            break
        fi
        sleep 1
        let _wait_seconds++
        echo "--- Wait ${_wait_seconds}s"
    done
    if [ $? -eq 0 ]; then
        echo "--- Stop successfully ${SERVER_FILE_NAME}"
        rm -rf ${_LOG_PATH}/server.pid
    else
        echo "--- Stop failure ${SERVER_FILE_NAME}"
    fi
    echo "----------------------------------------------------------------------------- Stop  [1] ------"
}
#
# =======================================
# 状态
# =======================================
status() {
    echo "----------------------------------------------------------------------------- status [0] ------"
    # 解析服务的 pid
    resolve_server_pid
    if [ "${_SERVER_PID}" -eq 0 ]; then
        echo -e "--- \033[33mStopped $SERVER_FILE_NAME\033[0m"
    else
        _SERVER_PORT_TEXT=`netstat -tulnp | grep "${_SERVER_PID}/" | awk 'BEGIN{ORS=" "}{print $4}'`
        [ -z "$_SERVER_PORT_TEXT" ] && _SERVER_PORT_TEXT="unknown "
        echo -e "--- \033[32mRunning ${SERVER_FILE_NAME} [ SERVER_PID = ${_SERVER_PID}, SERVER_PORT = ${_SERVER_PORT_TEXT}]\033[0m"
        echo -e "--- You can check the log file \033[36m${CONSOLE_FILE}\033[0m or execute the command on the next line"
        echo -e "--- \033[40;37mtail -f -n 300 ${CONSOLE_FILE}\033[0m"
    fi
    echo "----------------------------------------------------------------------------- status [1] ------"
}
#
# =======================================
# 日志
# =======================================
logs() {
    tail -f -n 3000 ${CONSOLE_FILE}
}
#
# ================================================ 方法 end   ================================================
#
case "$1" in
'start')
    start
    ;;
'stop')
    stop
    ;;
'restart')
    stop
    start
    ;;
'status')
    status
    ;;
'logs')
    logs
    ;;
*)
    echo "requires parameter [start|stop|restart|status|logs] [c]?"
    exit 1
    ;;
esac
#
#
#

  • 公众号:IT加载中(it_loading)
  • CSDN:https://blog.csdn.net/JinglongSource
  • 博客:https://ihouyu.cn/
  • 邮箱:for.houyu@qq.com

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/56177.html

相关文章

小编分享掌握这些技巧,你就是文案大神。

小编分享掌握这些技巧,你就是文案大神。

没两把刷子,称不上手艺人,靠写字吃饭,多少也算是个手艺人。 但是,文案圈子应该是所有的文字工作中最难混的圈子了,至于是不是手艺人中最难混的,这个没个标准,不予评价。 不过自古以来都有个规律,就是越难混的圈子,就越有很多的快捷技巧,今天,网站托管的小编我就跟大家分享一下这些技巧。...

开网店要准备什么(开网店要准备什么设备?)

开网店要准备什么(开网店要准备什么设备?)

开网店也是一种商业活动,与实体经营类似,在开店之前一定要做好市场调查,了解消费者的需求。例如,女性偏爱网购,女性产品比较热门,女装、女鞋、化妆品等的销售量均名列前茅。这也说明女性产品前景广阔,需求量大,而且更新速度较快。...

最常见的8种广告营销策略盘点

最常见的8种广告营销策略盘点

1、情感策略情感营销是以消费者的个人情感差异和需求为核心的企业营销策略,通过情感包装、情感、情感广告、情感口碑、情感设计等策略实现企业的经营目标。这时,消费者在购买商品时看重的不是商品的价格、数量和质量,而是一种情感满足和心理认同。情感营销从消费者的情感需求出发,激发消费者...

瑜伽馆营销策略,助力引流锁客,业绩飙升

瑜伽馆营销策略,助力引流锁客,业绩飙升

现在瑜伽馆的生意越来越难做,再不来点大招都难以生存下去了。今天企叮咚跟大家分享一个瑜伽馆的策略,希望给大家带来新的思路。瑜伽馆背景分析:整个瑜伽馆的装修环境、课程水平还是可以的,地理位置也还行,周围是高档小区,有比较充足的客源。但办卡率不高,学员的粘性不强。想要解决客源问题...

10月自播GMV超1000万,一家淘系男装品牌想借直播做品牌升级

10月自播GMV超1000万,一家淘系男装品牌想借直播做品牌升级

编辑导读:在女装品牌扎堆的服饰行业,男装品牌想要脱颖而出不是一件容易的事。本文作者以迈特优服饰官方旗舰店为例,分析其成功的原因,希望对你有帮助。 布局快手半年之后,男装品牌迈特优迎来爆发。10月16日,迈特优服饰官方旗舰店在快手单日自播GMV突破100万,10月累计GMV突破1...

小编分享如何利用自媒体推广(如何利用自媒体推广产品)

小编分享如何利用自媒体推广(如何利用自媒体推广产品)

有人说我们公司是做服务器的,品牌在有些知名度,但在全国没太高知名度,最近公司要利用互联网自平台宣传,然后就申请了微信公众号,但是具体怎么操作一窍不通! 首先产品很重要,对于自媒体运营的话就是说内容。比如可以从用户角度写使用后的感受,从渠道商的角度写什么产品好卖,从权威方的角度写什么产品好等等,...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片