如何在docker容器中修复ctrl + c

Jea*_*eri 19 shell kill-process docker

如果我连接到docker容器

$> docker exec -it my_container zsh
Run Code Online (Sandbox Code Playgroud)

在里面我想要杀死我开始的东西,ctrl+c我注意到它需要永远完成.我已经google了一下,似乎ctrl+c与你期望的有点不同.我的问题,如何ctrl+c在容器内修复?

NID*_*NID 22

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

从开始docker 0.6.5,您可以添加-t到docker run命令,它将附加一个pseudo-TTY.然后,您可以键入Control-C以从容器中分离而不终止它.

如果你使用-t-i再控制-C将终止该容器.使用时,-i with -t您必须使用Control-P Control-Q分离而不终止.

测试1:

$ ID=$(sudo docker run -t -d ubuntu /usr/bin/top -b)
$ sudo docker attach $ID
Control-P Control-Q
$ sudo docker ps
Run Code Online (Sandbox Code Playgroud)

容器仍然列出.

测试2:

$ ID=$(sudo docker run -t -i -d ubuntu /usr/bin/top -b)
$ sudo docker attach $ID
Control-C
$ sudo docker ps
Run Code Online (Sandbox Code Playgroud)

容器不存在(它已被终止).如果Control-P Control-Q在第二个示例中键入而不是Control-C,则容器仍将运行.

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

  • 我得到的印象(请纠正我,如果我错了)你所描述的`ctrl + c`是用于退出容器,这不是我想要的.我想停止我手动启动的程序 (3认同)
  • 请详细说明脚本如何阻塞容器进程,以及在 Ctrl-C 陷阱中应该做什么。 (2认同)

Kar*_*ara 9

when your docker terminal is not responding to Ctrl+C/Ctrl+D/Ctrl+/, try these steps:

#1>> Open another terminal session and enter the command:

    **`docker container ls`** 
        or
    **`docker container list`**


#2>> locate the container id from the above list and issue the docker container stop command:
    

**`docker stop <<containerId>>`**

#3>> next time when you launch the docker container, use the flag "**-it**"  to respond to the Ctrl+C event
    
Run Code Online (Sandbox Code Playgroud)

docker run -it <>

    Now you can stop ,with control+C
Run Code Online (Sandbox Code Playgroud)


eNc*_*Nca 8

当我尝试mdbook在 docker 容器中运行(Rust 可执行文件)时,我遇到了类似的问题。启动mdbook简单的网络服务器,我想通过Ctrl+停止它C,但这不起作用。

$ docker -ti --rm -p 4321:4321 my-docker-image mdbook serve --hostname 0.0.0.0 --port 4321
2019-08-16 14:00:11 [INFO] (mdbook::book): Book building has started
2019-08-16 14:00:11 [INFO] (mdbook::book): Running the html backend
2019-08-16 14:00:11 [INFO] (mdbook::cmd::serve): Serving on: http://0.0.0.0:4321
2019-08-16 14:00:11 [INFO] (ws): Listening for new connections on 0.0.0.0:3001.
2019-08-16 14:00:11 [INFO] (mdbook::cmd::watch): Listening for changes...
^C^C
Run Code Online (Sandbox Code Playgroud)

受到@NID's回答的启发,我通过通用bash脚本封装了mdbook可执行文件,docker-entrypoint.sh它做到了这一点(不需要显式捕获INT信号)。

$ docker -ti --rm -p 4321:4321 my-docker-image docker-entrypoint.sh mdbook serve --hostname 0.0.0.0 --port 4321
2019-08-16 14:00:11 [INFO] (mdbook::book): Book building has started
2019-08-16 14:00:11 [INFO] (mdbook::book): Running the html backend
2019-08-16 14:00:11 [INFO] (mdbook::cmd::serve): Serving on: http://0.0.0.0:4321
2019-08-16 14:00:11 [INFO] (ws): Listening for new connections on 0.0.0.0:3001.
2019-08-16 14:00:11 [INFO] (mdbook::cmd::watch): Listening for changes...
^C $
Run Code Online (Sandbox Code Playgroud)

内容docker-entrypoint.sh非常简单:

$ docker -ti --rm -p 4321:4321 my-docker-image mdbook serve --hostname 0.0.0.0 --port 4321
2019-08-16 14:00:11 [INFO] (mdbook::book): Book building has started
2019-08-16 14:00:11 [INFO] (mdbook::book): Running the html backend
2019-08-16 14:00:11 [INFO] (mdbook::cmd::serve): Serving on: http://0.0.0.0:4321
2019-08-16 14:00:11 [INFO] (ws): Listening for new connections on 0.0.0.0:3001.
2019-08-16 14:00:11 [INFO] (mdbook::cmd::watch): Listening for changes...
^C^C
Run Code Online (Sandbox Code Playgroud)


小智 7

在某些情况下,当我使用 ctrl-C 终止容器内的进程时,容器会终止。

此外,我见过在容器内运行的进程离开僵尸进程的情况。

我发现使用“--init”开关启动容器时,这两个问题都得到了解决。这似乎使我的容器以更“正常的、预期的类 UNIX 方式”运行。

如果您想了解有关“--init”开关作用的更多信息,请在包含“docker run”信息的 Docker 网页上阅读它。该网页上的信息显示“在转发信号和获取进程的容器内运行 init”。


ccj*_*351 6

我尝试了--init@Remy Orange 的解决方案,它对我有用。经过一番搜索,包括 i)如何在 docker run 中使用 --init 参数,ii) Tini 的优点是什么?iii) init,我写了下面的详细解决方案:

  1. tini在 Ubuntu 上安装:
  • 通过启动:
$ sudo apt update && sudo apt install tini
Run Code Online (Sandbox Code Playgroud)
  • 或者,如果tini在您的发行版中不可用或者太旧,请检查 Dockerfile 以在此处添加 tini 。
  1. 使用以下命令运行 Docker 容器--init
docker run -ti --init --rm YOUR_DOCKER_CONTAINER_EXMAPLE bash
Run Code Online (Sandbox Code Playgroud)
  1. 然后你进入你的 docker 容器,你可以运行一些进程或实验。例如,运行一个Python代码,然后你可以启动Ctrl + C来取消这个Python代码,就像你在Ubuntu上可以做的那样(即,位于docker容器之外的常规终端)。

  2. 请参阅我的案例的屏幕截图:

  • 启动Ctrl + C (i.e., ^C)取消 python 进程: 在此输入图像描述

  • 它停止了,KeyboardInterrupt并按预期显示: 在此输入图像描述


ase*_*ami 5

使用Ctrl+\而不是Ctrl+C
它会终止进程,而不是礼貌地要求它关闭。(在此处阅读更多内容。)

  • 它对我不起作用。当正在运行的 docker 容器没有响应“Ctrl+C”时,它也会忽略“Ctrl+\” (5认同)