如何在Docker容器内修复Ctrl+C

如何在Docker容器内修复Ctrl+C

简介

这篇文章的真正问题声明是,开发人员在运行或创建Docker容器时无法使用中断信号。这不是Docker中的一个bug,而是一个Linux特性。完整的问题和重新创建问题的方法与解决方案一起被解释。

Linux中的流程

目前正在运行或执行的程序是一个进程。这个进程可以是前台的,也可以是后台的。为了查看这些进程,我们有一些终端命令,如ps和top。ps显示活动进程,top显示进程的实时更新。

$ps

输出结果给你提供了进程ID、链接的tty、进程的时间以及实际运行的命令或程序。

输出

PID TTY        TIME CMD
2584 pts/0     00:00:00 bash
4146 pts/0     00:00:00 ps

要查看所有运行在你系统中的进程。

$ps –e

输出

PID TTY TIME CMD
   1 ? 00:00:02 systemd
   2 ? 00:00:00 kthreadd
   3 ? 00:00:00 rcu_gp
   4 ? 00:00:00 rcu_par_gp
   5 ? 00:00:00 netns
   .
   .
   .
   .
   3650 ? 00:00:01 kworker/1:0-cgroup_destroy
   3694 ? 00:00:00 kworker/u4:1-events_unbound
   4138 ? 00:00:00 kworker/0:1-cgroup_destroy
   4197 ? 00:00:00 kworker/0:2-events
   4198 pts/0 00:00:00 ps

在这里,我们有四千多个程序在运行。

Linux终端上的信号

信号或我们可以说是中断。这些信号是通过键盘快捷键发送到终端的。例如,为了粘贴,我们使用Ctrl+V。这将发送一个中断,使自己优先于其他正在进行的进程,并粘贴文本或图像。同样地,我们也有键盘快捷键来向Linux终端发送各种中断信号。这些信号在下面提到。

  • Tab

  • Ctrl+C

  • Ctrl+D

  • Ctrl+U

  • Ctrl+A

Tab

这个标签使用起来很有效率。它有助于命令的自动完成。它能识别命令的模式,并在按下时为你完成该命令。例如,停止容器4b534b34h34b34,$ docker stop 4b5,然后按tab键,它将获取完整的容器ID。

Ctrl+C

这个快捷方式将终止/中止/杀死当前执行的进程或命令。当命令被卡在一个循环中或你忘记了要添加到命令中的东西时,这很有用。只要用这个快捷方式终止命令,然后用编辑好的命令重新运行。

Ctrl+D

这个中断将杀死当前的用户终端并回溯到最后使用的用户终端。

Ctrl+U

这将删除完整的一行,并将光标移到该行的开头。

Ctrl+A

这将使光标回到命令的开头,而不删除命令。

重现问题的方法

执行下面给出的方法,在你的机器上重现这个问题。问题是,Docker容器对中断信号Ctrl+C没有反应。

方法1

在没有任何模式的情况下运行容器,并给出一个可以保持进程几秒钟的命令。

$docker run busybox sleep 10

输出

无论你按多少次Ctrl+C,你都没有得到任何回应。这个快捷方式应该是终止了在容器内运行的sleep 10命令。该命令得到完全执行。

方法2

在交互式模式下运行容器。应通过相同的睡眠命令并按下键盘上的快捷键。

$docker run -i busybox sleep 10

命令在容器内被执行。

方法3

现在使用-t标志添加tty选项,并检查是否有变化。

$docker run -t busybox sleep 10

同样的结果,命令被完全执行。

方法4

同时使用交互式和tty

$docker run -it busybox sleep 10

方法5

包括detach标志。

$docker run -itd busybox sleep 10

docker容器将在后台运行10秒。如果你在运行命令后刚按下Ctrl+C,它将不会对中断作出反应。

问题的解决方案

在解决这个问题之前,我们必须知道中断信号在上述方法中不起作用的原因。我们传递给容器的sleep命令得到了一个PID 1的进程ID。而PID 1对其他进程有一些特殊的权力。这就是中断不能终止PID 1或sleep命令的原因。

为了解决这个问题,docker提供了一个名为 --init 的选项。这将克服我们所有关于不同中断信号的问题。

$docker run --init busybox sleep 10

现在,Docker容器将响应Ctrl+C的中断,在没有完全执行的情况下终止命令sleep 10。

上述解决方案的证明

不用–init 用–init
$docker run busybox ps $docker run –init busybox ps
PID USER TIME COMMAND 1 root 0:00 ps PID USER TIME COMMAND 1 root 0:00 /sbin/docker-init — ps 7 root 0:00 ps

在第一种情况下,ps命令的PID是1,但在第二种情况下,PID 1是docker-init,这就是为什么我们能够在第二种情况下终止ps命令。

结论

有时小问题会卡住你的整个项目。这里我们讨论了各种中断信号,以及在特殊情况下如何将它们连接到docker容器。Docker不仅是学习容器化,而且是以最有效的方式使用它来实现我们的目标。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程