Ika*_*Ika 8 docker ubuntu-14.04
我正在使用tail -f/dev/null命令来保持容器.
该行本身放在一个前后有回声的脚本中.尾部-f/dev/null下的echo 预计是无法访问的,但出于某种原因我在日志中看到它.
一旦出现问题,每次重启容器都会导致容器启动并完成.只有rm和rebuild解决了这个问题.
我不确定它是否已连接,但我注意到在很短的时间内停止和启动计算机的一个问题帮助我重现了这个问题.
在什么情况下tail -f/dev/null可以继续下一行?
基本映像: ubuntu 64x,14.0.4
计算机操作系统: ubuntu 64x,14.0.4
小智 25
这是保持容器运行的更好方法
sleep infinity
Run Code Online (Sandbox Code Playgroud)
要回答您的问题在什么情况下tail -f /dev/null可能会完成并因此继续到 shell 脚本之类的下一行:
/dev/null(与 Linux 中的所有内容一样)是一个文件。当执行tail任何文件时,必须使用文件描述符打开该文件。它并不是tail -f /dev/null因为它已完成(它永远不会完成)而终止,而是因为对文件描述符的干扰而终止,这可能由于多种原因而发生,但是,在容器本身内部(很可能)没有其他事情发生会干扰文件描述符。
由于 docker 容器只是所谓的Linux 命名空间的一种奇特的覆盖,所以在容器内运行的所有进程(即使它在单独的 PID 命名空间内)实际上都在您的主机上运行。因此,由于某种原因,您的主机正在干扰您的文件描述符。
要检查进程创建的打开文件描述符,您可以执行以下命令:
$ sudo ls -la /proc/<pid>/fd
Run Code Online (Sandbox Code Playgroud)
您将在输出中看到某些数字:
0代表标准输入。1代表标准输出。2代表标准错误。其余的是进程正在打开的文件。
<pid>是您要查看的进程的 ID。当作为容器内的入口点运行时,容器内tail -f /dev/null很可能会包含 pid 。1为了在你的主机上找到 pid,你可以简单地用 grep 来查找它,如下所示:
$ sudo ps aux | grep 'tail -f /dev/null'
Run Code Online (Sandbox Code Playgroud)
要自己关闭文件描述符并手动重现在这些情况下会发生的情况,您可以使用GNU 调试器gdb。只需将调试器附加到您之前找到的 pid:
$ sudo gdb attach <pid>
Run Code Online (Sandbox Code Playgroud)
现在您可以继续选择要关闭的文件描述符(很可能它是数字,3因为该进程不会打开任何其他文件):
(gdb) call (int)close(3)
$1 = 0
Run Code Online (Sandbox Code Playgroud)
现在,在离开调试器时检查容器的日志:
(gdb) quit
Run Code Online (Sandbox Code Playgroud)
根据您的配置,您可能会tail在容器日志中看到错误:
tail: error reading '/dev/null': Bad file descriptor
Run Code Online (Sandbox Code Playgroud)
如前所述,还有一个标准错误的文件描述符 ( 2)。您可以重复整个过程并在同一调试器会话期间关闭标准错误和实际文件描述符:
(gdb) call (int)close(2)
$1 = 0
(gdb) call (int)close(3)
$2 = 0
(gdb) quit
Run Code Online (Sandbox Code Playgroud)
执行此操作后,容器日志中不会出现错误,并且如果是 bash 脚本,它将继续执行下一行。
为了检查到底是什么干扰了您的文件描述符,您必须在发生时广泛监视您的主机系统。
小智 -4
使用您选择的基础映像创建 Dockerfile(例如 Ubuntu 64 位 14.0.4)。在 Dockerfile 的末尾添加如下行:
ENTRYPOINT ["tail", "-f", "/dev/null"]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9020 次 |
| 最近记录: |