• Linux停止Java服务


    Linux停止Java服务,与selenium相关问题,部署脚本方案

    前言

    在部署一些不经过Jenkins的SpringBoot项目时,通常是自己编写nohup的java命令启动。重新部署时,使用JDK 自带的 jps 命令或者 Linux的 ps(process status) 命令来查出服务进程 ID,然后使用 linux kill -9命令杀死特定的进程。

    虽然在一般的教程或文章里,都说直接使用 kill -9 PID,其实这个是很粗暴的而且极其危险的动作。但由于程序不是关键业务,同时直接杀死在这些项目中也不会造成数据损失,也就没有过多在意。

    kill -9问题原因

    因为它不管程序现在有没有未处理完的事情,直接强制终止进程,这对于一些比较敏感的服务,例如金融交易等业务是致命的。

    比如说程序里使用了Springboot 的 ShutdownHook 钩子函数服务,或者实现了DisposableBean的接口,来实现服务正常关闭情况时,调用某些方法。如果程序时被kill -9 结束的,这些方法就会不会被调用,进而导致某些问题。

    程序中有selenium,使用kill -9的相关问题

    前文有说,如果使用kill -9结束进程会使程序无法调用钩子函数。而程序在使用selenium时,往往都会使用钩子函数,在结束程序前,就chrome浏览器进程和selenium的chromedriver驱动进程结束掉,以保证下次启动selenium的正常。

    所以如果程序使用了selenium,那就不能使用kill -9来结束程序进程!

    解决方案

    以下脚本是参考https://zhuanlan.zhihu.com/p/396444861和同事的脚本编写。

    #!/bin/bash
    
    APP_FILE=proxyIpCrawl-0.0.1-SNAPSHOT.jar
    
    CONF_NAME=test
    
    JAVA_OPTIONS_INITIAL=-Xms2048M
    
    JAVA_OPTIONS_MAX=-Xmx3072M
    
    APP_NAME=proxyIpCrawl-0.0.1
    
    PID=0
    
    function get_pid {
        javaps=`jps -l | grep $APP_FILE`
        if [ -n "$javaps" ]; then
           PID=`echo $javaps | awk '{print $1}'`
        else
           PID=0
        fi
    }
    
    
    function check_if_process_is_running {
        get_pid
        if [ $PID -ne 0 ]; then
        return 0
        fi
        return 1
    }
    function stop {
        echo -e "Waiting for process to stop"
        get_pid
        num=`expr $num + 1`  
        if [ $PID -ne 0 ]; then
            # 重试次数小于3次则继续尝试停止服务
            if [ "$num" -le 3 ];then
                echo "attempt to kill... num:$num"
                kill $PID
                sleep 1
            else
                # 重试次数大于3次,则强制停止
                echo "force kill..."
                # 结束Chromedriver进程
                ps aux | grep chromedriver | grep -v grep | awk '{print $2}' | xargs kill -9
                # 结束Chrome进程
                ps aux | grep chrome | grep -v grep | awk '{print $2}' | xargs kill -9
                # 结束java进程
                kill -9 $PID      
            fi
            # 检查上述命令执行是否成功
            if [ $? -eq 0 ]; then
                echo -e "kill -15 $APP_NAME run finished..."
            else
                echo -e "kill -15 $APP_NAME run failed..."
            fi
    
            # 重新获取进程ID,如果还存在则重试停止
            get_pid
            if [ $PID -ne 0 ]; then
                echo -e "$APP_NAME has running...retry"
                stop
            fi
        else
           echo "$APP_NAME not running"
        fi
    }
    
    case "$1" in
      status)
        if check_if_process_is_running
        then
          echo -e "$APP_NAME has running"
        else
          echo -e "$APP_NAME not ran"
        fi
        ;;
      stop)
        if ! check_if_process_is_running
        then
          echo  -e "$APP_NAME has stopped"
          exit 0
        fi
        stop
        ;;
      start)
        if check_if_process_is_running
        then
          echo -e "$APP_NAME has running"
          exit 1
        fi
        # 启动命令
        nohup java -jar $JAVA_OPTIONS_INITIAL $JAVA_OPTIONS_MAX $APP_FILE --spring.profiles.active=$CONF_NAME &
        echo -e "Starting"
        for i in {1..20}; do
            if ! check_if_process_is_running
            then
               echo -ne "."
               sleep 1
            fi
        done
        if ! check_if_process_is_running
        then
           echo  -e "$APP_NAME launch failed"
        else
           echo  -e "$APP_NAME has started"
        fi
        ;;
      restart)
        $0 stop
        if [ $? = 1 ]
        then
          exit 1
        fi
        $0 start
        ;;
      *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
    esac
    
    exit 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 脚本在stop进程时,会尝试执行3次kill -15命令来结束程序进程,kill -15命令就能够让程序正常调起钩子函数让程序完成需要完成的动作。如果3次都没有结束程序在使用kill -9 强制结束进程
    • 同时为了结束selenium相关进程,在强制结束进程时,还会使用管道命令将chrome和chromedriver进程一起杀死。如果你的程序没有使用selenium,可以删除这两条管道命令,同时根据你程序的需求自行编写其他命令
    • 其他程序使用该脚本只需要修改前五个常量即可
  • 相关阅读:
    HTML+CSS大作业:使用html设计一个简单好看的公司官网首页 浮动布局
    vuepress 配置文件分类管理
    内网可达网段探测netspy- Mac环境
    RabbitMQ——死信队列
    数组:
    【从零开始】Docker Desktop:听说你小子要玩我
    【Python】一文带你掌握数据容器之集合,字典
    Jquery中事件
    Vue中子组件向父组件传值$emit、.sync
    Android源码——TypedValue源码解析
  • 原文地址:https://blog.csdn.net/qq_43175022/article/details/131600324