【问题标题】:docker-compose down does not cascade down SIGTERM through two layers of bash scriptsdocker-compose down 不会通过两层 bash 脚本级联下 SIGTERM
【发布时间】:2024-01-10 18:54:01
【问题描述】:

我有两个 bash 脚本,一个作为我的 docker 容器的入口点,如下所示:

#!/bin/bash

sig_handler() 
{
  echo "[LAYER1] killing children with pid "$pid
  [[ $pid ]] && kill $pid
  exit 1
}

trap 'sig_handler' SIGINT SIGTERM

while true; do
  ./nextlayer.sh & pid=$!
  wait $pid
  echo "Waiting 5 seconds before starting a new worker..."
  sleep 5
done

现在 nextlayer.sh 也有某种信号捕获,但也尝试清理一些东西,如下所示:

#!/bin/bash

sig_handler() 
{
  echo "[LAYER2] Exiting main script and cleaning up tasks"
  cleanup
}

cleanup() 
{
  echo "[LAYER2] Cleaning up"
  sleep 5
  echo "Cleanup done, exiting with SIGTERM"
  exit 143
}

trap 'sig_handler' SIGINT SIGTERM

i=0
while [ $i -lt 10 ]
do
  i=$(( $i + 1 ))
  sleep 1
  echo $i
done

这只是在 i

但是,当将相同的逻辑应用于 docker 容器时,SIGTERM 仅在入口点脚本中到达 sighandler,但在第二层脚本中永远不会到达。有谁知道我做错了什么?

【问题讨论】:

  • 能详细解释一下docker是如何参与的吗?您是在一个 docker 容器中运行这两个脚本,还是第一个脚本和第二个脚本在不同的环境中运行(例如,一个在 docker 外部,另一个在内部,或两者都在不同的 docker 容器中)。
  • 两者都在 docker 中运行,第一个是调用第二个的入口点脚本。我找到了解决方案并将其发布为下面的答案:)
  • 你能不能把两层的wrapper都删掉,只设置主容器CMD直接运行worker?如果您需要多个工作进程,请从同一个映像启动多个容器。
  • @DavidMaze 我们的用例基本上是为 docker 复制类似 systemd 服务的东西。所以入口点执行 while true 循环并休眠 n 秒,直到它启动另一个工作程序。所以仅仅从 CMD 调用工人是不行的。

标签: bash docker signals


【解决方案1】:

我找到了解决办法。

在入口点脚本的 sig_handler 函数中,下面的等待指令解决了它:

sig_handler() 
{
    echo "[LAYER1] killing children with pid "$pid
    [[ $pid ]] && kill $pid
    wait $pid # this is crucial
    exit 1
}

所以在真正退出容器之前,等待 $pid 会强制它实际等待后续脚本的退出。我测试了这 5 次脚本迭代,一切正常。

【讨论】: