无法从“码头停止”中捕获TERM信号。

时间:2017-09-05 10:29:44

标签: python bash docker signals

这是我在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?

2 个答案:

答案 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 信号都直接到达我们上面设置的陷阱...... .

示例位于:https://github.com/iamdvr/docker-trap-subprocess

enter image description here