Docker 不响应终端中的 CTRL+C

Docker not responding to CTRL+C in terminal

目前 Docker 有问题;我将它用于 运行 图像,该图像会在启动时启动 ipython 笔记本。我希望对 ipython notebook 本身进行一些编辑,因此我需要在启动后将其关闭。

但是,在终端中按 CTRL+C 只会输入“^C”作为字符串。似乎没有使用 CTRL+C 实际关闭 ipython 笔记本实例的真正方法。

任何人都知道导致这种情况的原因,或者知道任何解决方案吗?

此 post 建议使用 CTRL-Z 作为将进程发送到后台然后通过其进程 ID 终止进程的解决方法: Cannot kill Python script with Ctrl-C

可能出现的问题:

  • 程序捕捉到 ctrl-c 但什么都不做,可能性很小。

  • 存在未正确管理的后台进程。只有主进程收到信号,子进程挂起。很可能发生了什么。

建议的解决方案:

  • 查看程序文档以了解如何正确启动和停止。 ctrl-c 似乎不是正确的方法。

  • 用 docker-entrypoint.sh bash 脚本包装程序,该脚本阻止容器进程并能够捕获 ctrl-c。这个 bash 示例应该有所帮助:https://rimuhosting.com/knowledgebase/linux/misc/trapping-ctrl-c-in-bash

  • 捕捉到 ctrl-c 后,为 ipython 笔记本调用正确的关机方法。

@maybeg 的回答已经很好地解释了为什么会发生这种情况。

关于停止无响应的容器,另一种解决方案是在另一个终端中简单地发出 docker stop <container-id>。与 CTRL-C 相反,docker stop 不发送 SIGINT 而是发送 SIGTERM 信号,进程可能对此做出不同的反应。

Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]

Stop a running container by sending SIGTERM and then SIGKILL after a grace period

如果失败,使用 docker kill <container-id> 立即发送 SIGKILL。

问题是 Ctrl-C 向容器内的顶级进程发送了一个信号,但该进程不一定会像您预期的那样做出反应。顶层进程在容器内的 ID 为 1,这意味着它不会获得进程通常具有的默认信号处理程序。如果顶级进程是 shell,那么它可以通过自己的处理程序接收信号,但不会将其转发给在 shell 中执行的命令。详细说明here。在这两种情况下,docker 容器的行为就好像它只是忽略了 Ctrl-C。

如果您要构建自己的映像,解决方案是 运行 一个最小的初始化进程,例如 tini or dumb-init,作为容器内的顶级进程。

来自 Docker 留言板上的 this post

打开一个新的shell并执行

$ docker ps # get the id of the running container
$ docker stop <container> # kill it (gracefully)

这对我来说效果很好。 CTRL-Z、CTRL-\ 等仅作为字符串出现,但这杀死了 Docker 容器并将选项卡返回到终端输入。

很可能您使用的容器镜像没有正确处理进程信号。 如果您正在创作图像,请按照 Roland Webers 的回答建议进行更改。 否则尝试 运行 它与 --init.

docker run -it --init ....

这为我修复了 Ctrl+C。 资料来源:https://docs.docker.com/v17.09/engine/reference/run/#specify-an-init-process