Linux优雅退出问题

简介: Linux优雅退出问题

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

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

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

a44d03214646245a2b905ec84d82d98e.png

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


6870f7dd878fbbecf6092258ab5b7919.png


还有一种情况是: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包,这样就会出现一系列的不可预知的错误.


目录
相关文章
|
4月前
|
存储 网络协议 Ubuntu
【Linux开发实战指南】基于UDP协议的即时聊天室:快速构建登陆、聊天与退出功能
UDP 是一种无连接的、不可靠的传输层协议,位于IP协议之上。它提供了最基本的数据传输服务,不保证数据包的顺序、可靠到达或无重复。与TCP(传输控制协议)相比,UDP具有较低的传输延迟,因为省去了建立连接和确认接收等过程,适用于对实时性要求较高、但能容忍一定数据丢失的场景,如在线视频、语音通话、DNS查询等。 链表 链表是一种动态数据结构,用于存储一系列元素(节点),每个节点包含数据字段和指向下一个节点的引用(指针)。链表分为单向链表、双向链表和循环链表等类型。与数组相比,链表在插入和删除操作上更为高效,因为它不需要移动元素,只需修改节点间的指针即可。但访问链表中的元素不如数组直接,通常需要从
268 2
|
5月前
|
Linux API
Linux线程总结---线程的创建、退出、取消、回收、分离属性
Linux线程总结---线程的创建、退出、取消、回收、分离属性
|
6月前
|
算法 Unix Linux
Linux进程与信号:正常与异常的退出机制探索
Linux进程与信号:正常与异常的退出机制探索
505 1
|
6月前
|
Shell Linux C语言
【Shell 命令集合 系统管理 内置命令】⭐⭐Linux 退出当前的Shell会话 exit命令 使用指南
【Shell 命令集合 系统管理 内置命令】⭐⭐Linux 退出当前的Shell会话 exit命令 使用指南
132 0
|
6月前
|
缓存 Unix Linux
【Linux】—— 进程的创建和退出
【Linux】—— 进程的创建和退出
|
6月前
|
运维 网络协议 Linux
linux/windows如何退出telnet
linux/windows如何退出telnet
330 0
|
6月前
|
Shell Linux
linux|shell编程|shell脚本的一些高级技巧(shell脚本内的括号,中括号,花括号,逻辑判断,脚本优雅退出等等)
linux|shell编程|shell脚本的一些高级技巧(shell脚本内的括号,中括号,花括号,逻辑判断,脚本优雅退出等等)
99 0
|
存储 小程序 Shell
【Linux】进程的创建、退出、等待和替换
一. 进程创建 — fork 1. 什么是fork()函数 头文件:#include <unistd.h>
|
Linux
linux基础——进程的退出及资源回收
linux基础——进程的退出及资源回收
455 0
linux基础——进程的退出及资源回收