【问题标题】:bash not reacting to signalsbash 对信号没有反应
【发布时间】:2018-12-21 12:15:16
【问题描述】:

让我们考虑以下脚本:

#!/bin/bash
while true ; do: ; done

运行脚本后,bash 进入循环,但可以中断(通过按 Ctrl-C 或发出 kill -2 命令)或终止(通过发出 kill 命令)。一切运作良好。但现在让我们考虑另一个脚本:

#!/bin/bash
sleep 60

运行此脚本后,bash 进程不再对 SIGINT 或 SIGTERM 信号作出反应。当然,它会对按下 Ctrl-C 或终止睡眠进程作出反应,但我感兴趣的是让 bash 进程本身对这些信号作出反应。我需要这个,因为我正在使用 bash 脚本作为入口点构建 Docker 映像,并且 Docker 将信号发送到容器中的 PID 1,在我的情况下,这将是 bash 进程。我正在努力使容器优雅地关闭。 Bash 进程不对信号做出反应,因此 Docker 将其杀死以关闭容器。

我们将不胜感激。

【问题讨论】:

  • 我建议您阅读hynek.me/articles/docker-signals,它解释了为什么信号处理可能是一个问题以及如何使其发挥作用。 tl;博士:您可能需要将exec--init 结合使用。

标签: bash docker sigint sigterm


【解决方案1】:

考虑这个 Docker 文件:

from centos:7

COPY entrypoint.sh /usr/bin/entrypoint.sh
RUN chmod 760 /usr/bin/entrypoint.sh

ENTRYPOINT ["/usr/bin/entrypoint.sh"]

带有对应的entrypoint.sh脚本

#!/usr/bin/env bash

function finish {
    # stop holding process here
    echo "exciting gracefully . . ."
    kill -TERM "$child" 2>/dev/null
    exit 0
}

trap finish SIGHUP SIGINT SIGQUIT SIGTERM

# your process which holds the container, eg
sleep 60 &
child=$!
wait "$child

构建镜像:

docker build --no-cache -t overflow .

运行镜像:

docker run overflow:latest

如果你在 60 秒内 CTRL+C 你会看到输出:

优雅地令人兴奋。 . .

显示信号首先杀死了你的脚本,然后是容器。

关于信号和容器的好资源可以在here找到

【讨论】:

  • 非常好。祝大家好运。
【解决方案2】:

如果你的 docker API 1.25+ 你可以运行容器

docker run --init -it

--init - 在容器内运行一个 init 来转发信号并获取进程 来自docker指南https://docs.docker.com/engine/reference/commandline/run/的描述

【讨论】:

  • 您能否通过问题编辑来扩展 --init 的功能?我认为你的回答是正确的,但它可能会受益于更多的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 1970-01-01
  • 2017-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多