这是我在CMD中使用的bash脚本
#!/bin/bash
set -eo pipefail
echo "Setting trap"
echo $$
echo $BASHPID
trap 'cleanup' TERM
trap 'cleanup' KILL
cleanup() {
echo "Cleaning up..."
kill -TERM `jobs -p`
}
# To start the essential services
service ntp start
service awslogs start
cd /app
python -m job_manager &
wait
Docker文件不是很有趣
FROM ubuntu:16.04
RUN apt-get update --fix-missing && apt-get install -y \
git \
python \
python-pip \
ntp \
curl
ENV APP_HOME /app
RUN mkdir -p ${APP_HOME}
COPY src/ ${APP_HOME}/
# job-cmd.sh is kept here
COPY docker/helper-files/* /
CMD /job-cmd.sh
这个想法是将TERM信号捕获到job-cmd.sh中,然后传递给python任务。
我已经尝试了很多次但是没有用。我添加这些电话后
echo $$
echo $BASHPID
我意识到CMD过程的pid实际上是7而不是1,正如我所料。
我的问题:
1)为什么bash过程被分配PID 7?
2)如何修复我的作业脚本/ dockerfile?
答案 0 :(得分:1)
我认为这种情况正在发生,因为您正在使用shell
指令的CMD
形式。来自https://docs.docker.com/engine/reference/builder/#cmd:
如果要在没有shell的情况下运行命令,则必须将该命令表示为JSON数组并提供可执行文件的完整路径。此数组形式是CMD的首选格式。
因此,请将CMD
中的Dockerfile
指令替换为:
CMD ["/job-cmd.sh"]
然后,您的Bash流程将被分配PID 1
。您的TERM
处理程序可以正常运行,但您无法捕获KILL
信号。来自man trap
:
陷阱SIGKILL或SIGSTOP在语法上被一些历史实现所接受,但它没有任何效果。便携式POSIX应用程序无法捕获这些信号。
仅供参考,我在此解释了PID 1
问题的更多信息:https://serverfault.com/questions/869543/bash-script-entrypoint-pid-1-kills-tail-sub-process-only-if-a-fake-trap-whi/870872#870872
答案 1 :(得分:0)
您可以在 bash 中使用 trap 命令来执行此操作。
#!/bin/bash
#
function gracefulShutdown {
echo "Shutting down!"
# do something..
}
trap gracefulShutdown SIGTERM TERM INT
./subprocess.sh &
tail --pid=${!} -f /dev/null &
wait "${!}"
tail 命令只是等待子进程完成,而 wait 命令等待尾部完成......现在,主进程正在等待......所以任何 docker 信号都直接到达我们上面设置的陷阱...... .