type
status
date
slug
summary
tags
category
icon
password
文章状态
什么是信号?
信号是 Linux 内核与进程以及进程间通信的一种方式。
其应用于异步事件的处理,实质上是一种软中断。
针对每个信号进程都有个默认的动作,不过进程可以通过定义信号处理程序来覆盖默认的动作,除了SIGSTOP
和SIGKILL
。此二者都不能被捕获或重写,前者用来将进程暂停在当前状态,而后者则是从内核层面立即杀掉进程。
- 暴力与优雅
有两个比较重要的进程
SIGTERM
和 SIGKILL
:SIGTERM
是优雅地关闭命令,SIGKILL
则是暴力的关闭命令。比如 Docker,容器会先收到
SIGTERM
信号,10s 后会收到 SIGKILL
信号。Kill 参数
使用kill -l
可以查看 Linux 系统中的所有信号,如下:
信号值 | 信号名 | 说明 | 备注 |
1 | SIGHUP | 启动被终止的程序,可让该进程重新读取自己的配置文件,类似重新启动。 | ㅤ |
2 | SIGINT | 相当于用键盘输入 [ctrl]-c 来中断一个程序的进行。 | interrupt |
9 | SIGKILL | 代表强制中断一个程序的进行。若该程序进行到一半,那么尚未完成的部分可能会有“半产品”产生,类似 vim 会有 .filename.swp 保留下来。 | kill,此信号无法捕捉 |
15 | SIGTERM | 以正常的方式来终止该程序。由于是正常的终止,所以后续的动作仍会完成。然而,若该程序已经发生问题——无法使用正常的方法终止时,此信号也是无用的。 | terminate |
19 | SIGSTOP | 相当于用键盘输入 [ctrl]-z 来暂停一个程序的进行。 | stopped,此信号无法捕捉 |
当容器接收到信号…
只有容器中的 1 号进程能够收到信号。
容器中的进程属于容器的 1 号进程
Docker 的
stop
和 kill
命令都是用来向容器发送信号的。docker stop
命令会首先发送 SIGTERM
信号,并等待应用优雅的结束(此时间用户可指定);如果发现应用没有结束,docker 会再发送一个
SIGKILL
信号强行结束程序。docker kill
命令默认发送的是 SIGKILL
信号,用户可通过 -s
标签指定任何信号。步骤一:准备捕捉信号后做出动作的代码
通常由 Dev 提供
步骤二:编写测试环境的 Dockerfile
直接启动步骤一中准备的 APP,即程序为 1 号进程
构建镜像,测试信号
容器中的进程不属于容器的 1 号进程
步骤一:创建启动程序的 app1.sh
脚本文件
通过脚本启动程序,即程序非 1 号进程
步骤二:编写测试环境的 Dockerfile
构建镜像,测试信号
在脚本中捕获信号
步骤一:创建可捕捉信号的 app2.sh
脚本文件
步骤二:编写测试环境的 Dockerfile
构建镜像,测试信号
使用 tini 作为容器启动入口
Docker 1.13 之后版本包含 Tini 在其中
Tini 是一个为容器设计的微小但有效的
init
系统。其主要用于在一个容器中启动一个单一的子进程,并等待其退出,同时负责回收僵尸进程和进行信号转发:
- 回收僵尸进程
Tini 能够有效地回收僵尸进程,避免它们占用系统资源。
- 信号转发
Tini 能够将信号转发给子进程,确保子进程能够正确地处理这些信号。
在执行
docker run
命令时,通过指定 --init
参数,Docker 会自动将 Tini 程序(位于 /sbin/docker-init
)注入到容器中,并将其设置为容器的初始化进程。这一操作会覆盖原有的 ENTRYPOINT
配置,使得容器内的主进程在 Tini 的管理下运行。Tini 作为 PID 1 的进程,负责启动并监控容器内的主进程,同时处理僵尸进程的回收和信号的转发。- 作者:yomax66
- 链接:https://yomax66.xyz//learning/graceful_termination
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。