简体   繁体   English

docker日志和缓冲输出

[英]docker logs and buffered output

I want to continously print dots without newline (waiting behavior). 我想连续打印没有换行的点(等待行为)。

This bash one-liner works fine on my machine: 这个bash one-liner在我的机器上工作正常:

$ while true; do sleep 1; printf '.'; done
.......^C

However, when I run it in a Docker container, and when I try to read its output with docker logs, no output is printed: 但是,当我在Docker容器中运行它时,当我尝试使用docker日志读取其输出时,不会打印输出:

$ docker run -d --name test_logs ubuntu:14.04 bash -c "while true; do sleep 1; printf '.'; done"
60627015ed0a0d331a26e0c48ccad31c641f2142da55d24e10f7ad5737211a18
$ docker logs test_logs
$ docker logs -f test_logs
^C

I can confirm that the bash loop is executing in the container by using strace on process 1 (bash command): 我可以通过在进程1(bash命令)上使用strace来确认bash循环正在容器中执行:

$ docker exec -t test bash -c 'apt-get install -y strace; strace -p1 -s9999 -e write'
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  strace
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 113 kB of archives.
After this operation, 504 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ trusty/main strace amd64 4.8-1ubuntu5 [113 kB]
Fetched 113 kB in 0s (154 kB/s)
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
Selecting previously unselected package strace.
(Reading database ... 11542 files and directories currently installed.)
Preparing to unpack .../strace_4.8-1ubuntu5_amd64.deb ...
Unpacking strace (4.8-1ubuntu5) ...
Setting up strace (4.8-1ubuntu5) ...
Process 1 attached
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=136, si_status=0, si_utime=0, si_stime=0} ---
write(1, ".", 1)                        = 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=153, si_status=0, si_utime=0, si_stime=0} ---
write(1, ".", 1)                        = 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=154, si_status=0, si_utime=0, si_stime=0} ---
write(1, ".", 1)                        = 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=155, si_status=0, si_utime=0, si_stime=0} ---
write(1, ".", 1)                        = 1

...and so on. ...等等。

Also, it works fine when directly watching output with option -t (without using docker logs ): 此外,使用选项-t (不使用docker logs )直接观看输出时,它可以正常工作:

$ docker run -t --name test_logs ubuntu:14.04 bash -c "while true; do sleep 1; printf '.'; done"
...........^C

Even weirder, background + pseudo-tty (option -d + option -t ) worked once, but then didn't work anymore. 甚至更奇怪,背景+伪tty(选项-d +选项-t )工作一次,但后来不再工作了。

printf is a line-buffered command, and if I add flushing by printing a newline character, it works: printf是一个行缓冲命令,如果我通过打印换行符添加刷新,它可以工作:

$ docker run -d --name test_logs ubuntu:14.04 bash -c "while true; do sleep 1; printf '.\n'; done"
720e274fcf85f52587b8a2a402465407c5e925c41d80af05ad3a73cebaf7110f
$ docker logs -f test_logs
.
.
.
.
.
.
^C

So I tried to "unbuffer" printf with stdbuf, without any success: 所以我尝试用stdbuf“unbuffer” printf ,没有任何成功:

$ docker run -d --name test_logs ubuntu:14.04 bash -c "while true; do sleep 1; stdbuf -o0 printf '.'; done"
2ba2116190c1b510288144dc5a220669f52f701c17f6f102e6bd6af88de4674e
$  docker logs test_logs
$ docker logs -f test_logs
^C

Next I tried to redirect printf to the standard error, still without success: 接下来我尝试将printf重定向到标准错误,仍然没有成功:

$ docker run -d --name test_logs ubuntu:14.04 bash -c "while true; do sleep 1; printf '.' >&2; done"
b1645b48bd9afd5b72318fba5296157ce1c0346f6a82fa166e802a979c1b0b0f
$ docker logs test_logs
$ docker logs -f test_logs
^C

...and with both at the same time, still without success: ......并且两者同时仍然没有成功:

$  docker run -d --name test_logs ubuntu:14.04 bash -c "while true; do sleep 1; stdbuf -o0 printf '.' >&2; done"

I encountered the same behaviour when using echo -n instead of printf . 使用echo -n而不是printf时遇到了相同的行为。

My questions: Do I unbuffer correctly? 我的问题:我是否正确地解压缩? If yes, what makes it not working? 如果是的话,是什么让它无法运作?

Looking for insight on this :) 寻找对此的见解:)

The default docker logging driver (json-file) does not supported unbuffered output. 默认的docker日志记录驱动程序(json-file)不支持无缓冲输出。 You will eventually see your dots, but only after the buffer has been filled. 你最终会看到你的点,但只有在填充缓冲区之后。

If you need unbuffered output, you can use the syslog logging driver. 如果需要无缓冲输出,可以使用syslog日志记录驱动程序。 However, because it's syslog, I doubt that will give you what you want since it will be delivering unbuffered output to syslog. 但是,因为它是系统日志,我怀疑它会给你你想要的东西,因为它将向syslog提供无缓冲的输出。 Documented here on docs.docker.com 在docs.docker.com上记录

Since running dots are usually useful only in interactive situations where seeing more dots means that work is continuing, you may just want to put out a periodic status with a newline so docker logs gives you better information. 由于运行点通常仅在交互式情况下有用,因为看到更多点意味着工作正在继续,您可能只想使用换行符来定期状态,以便docker logs为您提供更好的信息。

The solution here is usually to check to see if you are in interactive mode, and if so, show the dots: 这里的解决方案通常是检查您是否处于交互模式,如果是,则显示点:

#!/bin/bash
while true; do
     if [ -t ]; then
         echo -n .
     elif ((++COUNT % 60 == 0)); then
         echo "$(date) still in progress"
     fi
     sleep 1   # or whatever work is going on
done

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM