linux - 为什么 SIGHUP 在 Alpine Docker 容器中的 busybox sh 上不起作用?
问题描述
发送SIGHUP
_
kill -HUP <pid>
到busybox sh
我的本机系统上的进程按预期工作并且外壳挂起。但是,如果我使用docker kill
将信号发送到容器
docker kill -s HUP <container>
它什么也没做。Alpine 容器仍在运行:
$ CONTAINER=$(docker run -dt alpine:latest)
$ docker ps -a --filter "id=$CONTAINER" --format "{{.Status}}"
Up 1 second
$ docker kill -s HUP $CONTAINER
4fea4f2dabe0f8a717b0e1272528af1a97050bcec51babbe0ed801e75fb15f1b
$ docker ps -a --filter "id=$CONTAINER" --format "{{.Status}}"
Up 7 seconds
顺便说一句,使用 Ubuntu 容器(运行bash
)它确实可以按预期工作:
$ CONTAINER=$(docker run -dt debian:latest)
$ docker ps -a --filter "id=$CONTAINER" --format "{{.Status}}"
Up 1 second
$ docker kill -s HUP $CONTAINER
9a4aff456716397527cd87492066230e5088fbbb2a1bb6fc80f04f01b3368986
$ docker ps -a --filter "id=$CONTAINER" --format "{{.Status}}"
Exited (129) 1 second ago
发送SIGKILL
确实有效,但我宁愿找出原因SIGHUP
。
更新:我将添加另一个示例。在这里您可以看到busybox sh
通常确实挂断SIGHUP
成功:
$ busybox sh -c 'while true; do sleep 10; done' &
[1] 28276
$ PID=$!
$ ps -e | grep busybox
28276 pts/5 00:00:00 busybox
$ kill -HUP $PID
$
[1]+ Hangup busybox sh -c 'while true; do sleep 10; done'
$ ps -e | grep busybox
$
但是,在 docker 容器内运行相同的无限睡眠循环不会退出。如您所见,容器仍在运行之后SIGHUP
,仅在之后退出SIGKILL
:
$ CONTAINER=$(docker run -dt alpine:latest busybox sh -c 'while true; do sleep 10; done')
$ docker ps -a --filter "id=$CONTAINER" --format "{{.Status}}"
Up 14 seconds
$ docker kill -s HUP $CONTAINER
31574ba7c0eb0505b776c459b55ffc8137042e1ce0562a3cf9aac80bfe8f65a0
$ docker ps -a --filter "id=$CONTAINER" --format "{{.Status}}"
Up 28 seconds
$ docker kill -s KILL $CONTAINER
31574ba7c0eb0505b776c459b55ffc8137042e1ce0562a3cf9aac80bfe8f65a0
$ docker ps -a --filter "id=$CONTAINER" --format "{{.Status}}"
Exited (137) 2 seconds ago
$
解决方案
(我手头没有 Docker 环境可供尝试。只是猜测。)
对于您的情况,docker run
必须运行busybox/sh
或bash
作为PID 1。
根据 Docker文档:
注意:在容器内以PID 1运行的进程会被 Linux 特殊处理:它会忽略任何具有默认操作的信号。因此,该过程不会终止
SIGINT
或SIGTERM
除非它被编码这样做。
对于busybox / sh和bash之间关于SIGHUP
---
在我的系统(Debian 9.6,x86_64)上, 和 的信号掩码busybox/sh
如下bash
:
忙箱/sh:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 82817 0.0 0.0 6952 1904 pts/2 S+ 10:23 0:00 busybox sh
PENDING (0000000000000000):
BLOCKED (0000000000000000):
IGNORED (0000000000284004):
3 QUIT
15 TERM
20 TSTP
22 TTOU
CAUGHT (0000000008000002):
2 INT
28 WINCH
重击:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 4871 0.0 0.1 21752 6176 pts/16 Ss 2019 0:00 /usr/local/bin/bash
PENDING (0000000000000000):
BLOCKED (0000000000000000):
IGNORED (0000000000380004):
3 QUIT
20 TSTP
21 TTIN
22 TTOU
CAUGHT (000000004b817efb):
1 HUP
2 INT
4 ILL
5 TRAP
6 ABRT
7 BUS
8 FPE
10 USR1
11 SEGV
12 USR2
13 PIPE
14 ALRM
15 TERM
17 CHLD
24 XCPU
25 XFSZ
26 VTALRM
28 WINCH
31 SYS
正如我们所见,busybox/sh无法处理SIGHUP
,因此信号被忽略。Bash捕获SIGHUP
,因此docker kill
可以将信号传递给 Bash,然后 Bash 将被终止,因为根据其手册,“shell 在收到 a 时默认退出SIGHUP
”。
更新 2020-03-07 #1:
快速测试了一下,我之前的分析基本正确。你可以这样验证:
[STEP 104] # docker run -dt debian busybox sh -c \
'trap exit HUP; while true; do sleep 1; done'
331380090c59018dae4dbc17dd5af9d355260057fdbd2f2ce9fc6548a39df1db
[STEP 105] # docker ps
CONTAINER ID IMAGE COMMAND CREATED
331380090c59 debian "busybox sh -c 'trap…" 11 seconds ago
[STEP 106] # docker kill -s HUP 331380090c59
331380090c59
[STEP 107] # docker ps
CONTAINER ID IMAGE COMMAND CREATED
[STEP 108] #
正如我之前所展示的,默认情况下busybox/sh
不会捕获SIGHUP
,因此信号将被忽略。但是在busybox/sh
显式陷阱之后SIGHUP
,信号将被传递给它。
我也试过SIGKILL
了,是的,它总是会终止正在运行的容器。这是合理的,因为SIGKILL
不能被任何进程捕获,因此信号将始终传递到容器并杀死它。
更新 2020-03-07 #2:
您也可以通过这种方式验证它(更简单):
[STEP 110] # docker run -ti alpine
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
7 root 0:00 ps
/ # kill -HUP 1 <-- this does not kill it because linux ignored the signal
/ #
/ # trap 'echo received SIGHUP' HUP
/ # kill -HUP 1
received SIGHUP <-- this indicates it can receive SIGHUP now
/ #
/ # trap exit HUP
/ # kill -HUP 1 <-- this terminates it because the action changed to `exit`
[STEP 111] #
推荐阅读
- reactjs - 片段内的反应组件未加载
- java - 在屏幕 1 的文本字段中保留值,同时使用变量和意图从屏幕 2 按下回
- react-native - React Native 会执行 Tree Shaking 吗?
- ibm-cloud - softlayer 带宽池删除
- dart - 每隔一定时间间隔选择地理位置
- c - C - 检查主要参数
- android - 无法连接到 Android 模拟器 Windows 操作系统上的开发服务器?
- android - 当应用程序处于后台或在 android 中关闭时,FCM 通知未在通知栏中显示可扩展图像
- java - Activity 的 onCreate 方法上的 NullPointerException。必须在 setContentView() 之前动态添加视图
- jquery - 是否可以像'Jquery'附加元素一样在角度4中动态创建元素?