zoukankan      html  css  js  c++  java
  • Linux优雅退出问题

    问题:Springboot框架开发的项目中会内嵌tomcat容器,在杀死进程的时候tomcat为被正常杀死,导致端口未被释放,第二次启动的时候报端口冲突。

    先讲一个基本概念:如何在shell中终止一个后台进程?

     kill的作用是向某个指定的进程或进程组发送指定信号,从而结束该进程/进程组。-s选项可以指定要发送的具体信号,如果没有指定,则默认发送SIGTERM(15)信号至指定进程/进程组,若进程没有捕获该信号的逻辑,则SIGTERM的作用是终止进程。

    kill pid与kill -9 pid的区别
    kill pid的作用是向进程号为pid的进程发送SIGTERM(这是kill默认发送的信号,信号值为15),该信号是一个结束进程的信号且可以被应用程序捕获。若应用程序没有捕获并响应该信号的逻辑代码,则该信号的默认动作是kill掉进程。这是终止指定进程的推荐做法。
    kill -9 pid则是向进程号为pid的进程发送SIGKILL(该信号的编号为9),从本文上面的说明可知,SIGKILL既不能被应用程序捕获,也不能被阻塞或忽略,其动作是立即结束指定进程。通俗地说,应用程序根本无法“感知”SIGKILL信号,它在完全无准备的情况下,就被收到SIGKILL信号的操作系统给干掉了,显然,在这种“暴力”情况下,应用程序完全没有释放当前占用资源的机会。事实上,SIGKILL信号是直接发给init进程的,它收到该信号后,负责终止pid指定的进程。关于linux init进程的说明,可以参考这里这里。在某些情况下(如进程已经hang死,无法响应正常信号),就可以使用kill -9来结束进程。
    若通过kill结束的进程是一个创建过子进程的父进程,则其子进程就会成为孤儿进程(Orphan Process),这种情况下,子进程的退出状态就不能再被应用进程捕获(因为作为父进程的应用程序已经不存在了),不过应该不会对整个linux系统产生什么不利影响。

    stop() {
        echo "Stopping $serviceName"
        echo "Testing dir..."
        checkDirWritable
        if [[ $? -ne 0 ]]; then
          echo_failure;
          return 1
        fi
        [ ! -f $PID_FILE ] && {
          echo "Stop: not exist pid file, return directly"
            echo_failure;
            return 0
        }
        PID=`cat $PID_FILE`
        RETVAL=$?
        [ -z "$PID" ] && {
          echo "Stop fail: empty pid file"
            echo_failure; #empty pid value"
            return 1;
        }
        echo "Searching process with pid: $PID"
        ps -p "$PID" >/dev/null 2>&1
        if [ $? -eq 0 ]; then
          echo "PID($PID) exist, stopping process..."
            #用kill命令杀死进程=====================
            kill $PID >/dev/null 2>&1
            RETVAL=$?
            [ $RETVAL -eq 0 ] || {
              echo "Stop fail: could not kill process"
                echo_failure; # could not kill process
                return 2
            }
          echo "Stop exiting process success"
        else
          echo "Cannot find process with pid: $PID"
        fi
        
        rm -f $PID_FILE; # Remove control files
        rm -f $LOK_FILE
        echo_success
        return 0
    }

    上面也已经提到了:因为springboot项目中会内嵌tomcat容器  在kill进程的时候在被进程捕获后tomcat关闭需要一些时间,如果stop之后不休眠一定时间 有可能会导致tomcat未能正常关闭,导致第二次启动的时候报端口冲突,第二次有Pid但是进程没有成功启动。

    所以我们在这里调整stop之后休眠10s在启动start

    还有一种情况是:setsockopt中参数SO_REUSEADDR

    一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。 SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。TCP,先调用close()的一方会进入TIME_WAIT状态。

    我们知道,在TCP断开链接的时候我们需要四次握手来断开,而且当两端都关闭了read/write通道以后我们还是要等待一个TIME_WAIT时间。

    这就是SO_REUSEADDR的作用所在.其实这个选项就是告诉OS如果一个端口处于TIME_WAIT状态, 那么我们就不用等待直接进入使用模式, 不需要继续等待这个时间结束.

    那这样我们肯定要问,那为什么我们需要有这个TIME_WAIT时间啊?

    看看TCP/IP协议组我们就知道,这样做是为了让在网络中残余的TCP包消失, 也就是说, 如果我们没有等到这个时间就让OS把这个端口释放给其他的进程使用,别的进程很有可能就会收到上一个会话的残余TCP包,这样就会出现一系列的不可预知的错误.

  • 相关阅读:
    CGI编程完全手册(转)
    Linux下读写芯片的I2C寄存器(转)
    Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析
    H264中的SPS、PPS提取与作用(转)
    H264码流打包分析(精华)--转
    嵌入式Linux USB WIFI驱动的移植(转)
    推荐一款技术人必备的接口测试神器:Apifox
    Java 设置、删除、获取Word文档背景(基于Spire.Cloud.SDK for Java)
    Java 添加、删除、格式化Word中的图片( 基于Spire.Cloud.SDK for Java )
    Java 添加、删除、替换、格式化Word中的文本(基于Spire.Cloud.SDK for Java)
  • 原文地址:https://www.cnblogs.com/lingyejun/p/7358365.html
Copyright © 2011-2022 走看看