首页 > 解决方案 > Docker su 信号陷阱和 PID 1

问题描述

当我使用docker 容器中的入口点bash 脚本su中的命令执行脚本时, PID 更改(新的 PID 不同于)并且不会捕获任何终止信号1

此命令在我的主机(debian)上运行良好:

# Here I am root
su user1 -s './user.sh'

我认为主要问题是用户脚本在另一个进程中执行并且信号流被破坏。正如您在代码(docker.sh)中看到的那样,我尝试了许多命令但没有令人满意的行为。我想避免使用该exec命令,因为我需要入口点脚本来对 kill 信号执行许多清理任务

root 用户如何通过在 docker 容器中正确捕获信号来运行用户脚本?

Dockerfile

FROM ubuntu:latest
STOPSIGNAL SIGTERM
WORKDIR /app
COPY docker.sh user.sh ./
CMD ["/bin/bash", "-c", "./docker.sh"]

码头工人.sh

#!/bin/bash

echo "################################################"
echo "[DOCKER] Started"

handleSignal()
{
    echo "[DOCKER] Killed"
    exit 0
}

trap handleSignal SIGTERM SIGINT SIGHUP

echo "[DOCKER] $$ $(whoami)"

if [ -z "$(id -u user1 2> /dev/null)" ]
then
    useradd -s /bin/bash user1
    echo "[DOCKER] User 'user1' created"
fi

su user1 -s './user.sh' # PID is not 1, no signal
# su user1 -c './user.sh' # PID is not 1, no signal
# su -l user1 -c './user.sh' # PID is not 1, no signal
# su user1 --session-command='./user.sh' # PID is not 1, no signal
# su -l user1 --session-command='./user.sh' # PID is not 1, no signal
# su - user1 -s './user.sh' # PID is not 1, no signal
# su -l user1 -s './user.sh' # PID is not 1, no signal
# su user1 -c 'bash -c ./user.sh' # PID is not 1, no signal
# su user1 -c 'exec bash -c ./user.sh' # PID is not 1, no signal
# runuser user1 -c './user.sh' # PID is not 1, no signal
# runuser user1 -s './user.sh' # PID is not 1, no signal
# runuser -l user1 -c './user.sh' # PID is not 1, no signal
# runuser user1 --session-command='./user.sh' # PID is not 1, no signal

# ./user.sh # PID is not 1, user is not user1, no signal
# bash -c ./user.sh # PID is not 1, user is not user1, no signal

# exec ./user.sh # user is not user1, only user.sh trap signal
# exec bash -c 'exec ./user.sh' # user is not user1, only user.sh trap signal

# exec su user1 -c './user.sh' # PID is not 1, only user.sh trap signal
# exec su user1 -s './user.sh' # PID is not 1, only user.sh trap signal
# exec su -l user1 -s './user.sh' # PID is not 1, only user.sh trap signal
# exec su user1 --session-command='./user.sh' # PID is not 1, only user.sh trap signal
# exec su - user1 --session-command='./user.sh' # PID is not 1, only user.sh trap signal
# exec su -l user1 --session-command='./user.sh' # PID is not 1, only user.sh trap signal

echo "[DOCKER] Stopped"

用户.sh

#!/bin/bash

handleSignal()
{
    echo "[USER] Kill signal received"
    kill -TERM $child
}

trap handleSignal SIGTERM SIGINT SIGHUP

echo "[USER] $$ $(whoami)"

sleep 100 &

child=$!

wait $child

echo "[USER] Exited"

日志与su user1 -s './user.sh'

[DOCKER] Started
[DOCKER] 1 root
[DOCKER] User 'user1' created
[USER] 11 user1

Docker 在 10 秒超时后终止了容器。没有信号被捕获。

日志与exec su user1 -s './user.sh'

[DOCKER] Started
[DOCKER] 1 root
[DOCKER] User 'user1' created
[USER] 10 user1
[USER] Kill signal received
[USER] Exited
Session terminated, killing shell... ...killed.

容器已停止,但入口点脚本 (docker.sh) 中的信号处理程序由于 exec 未执行

预期日志

[DOCKER] Started
[DOCKER] 1 root
[DOCKER] User 'user1' created
[USER] 1 user1
[USER] Kill signal received
[USER] Exited
[DOCKER] Killed

无论如何,如果信号被正确捕获但用户脚本在另一个进程(PID)中执行,那会很好。

标签: bashdockersignalspidsu

解决方案


推荐阅读