bash - 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)中执行,那会很好。
解决方案
推荐阅读
- c - 在单独的头文件中定义的类型的 typedef
- angular - 我的 ngx 翻译器无法在 Ionic4 中获取当前语言
- python - 如何仅提取 javadoc 注释的初始描述并使用 python 忽略 javadoc 标记?
- sas - 如何记录 SAS 启动次数?
- refresh - 如何在 Angular ng-multiselect-dropdown 更改时刷新数据输入
- crm - 在 vTiger7 中逐步使用 vtlib 的自定义模块
- amazon-athena - AWS Glue Crawler - 未正确获取时间戳列(始终定义为字符串)
- html - 如何不让可访问性专注于复选框
- django - 访问另一个视图的 url 名称
- mysql - 当现有连接的结果为空时,MySQL 新连接