在容器的docker日志中查找字符串

182
什么是在docker容器日志中查找特定字符串的最佳方法?比如说,我想要查看所有来自以"127."开头的ip的"nginx" docker镜像所做的请求。

在docker日志命令上使用grep无法按预期工作:

docker logs nginx | grep "127."

它会打印所有日志,但不会筛选结果!


问题是:在Docker容器的日志中找到特定字符串的最佳方法是什么? - Gering
docker logs 命令是否将输出发送到标准输出?如果是,则 grep 应该可以正常工作。如果不是,则需要将标准错误重定向到标准输出,然后再使用 grep 进行过滤。 - Etan Reisner
3
检查 stderr 和 stdout,从 https://github.com/docker/docker/issues/7440 提取 $ docker run -d --name foo busybox ls abcd $ docker logs foo > stdout.log 2>stderr.log $ cat stdout.log $ cat stderr.log ls: abcd: No such file or directory - user2915097
1
@Robse 抱歉,在你添加示例之前,我很难理解你的问题。看起来 docker logs 很难使用 grep,因为它包含终端控制字符。我建议通过 nginx 日志文件进行 grep。 - hek2mgl
不知道你是否能在使用--follow时实现这个功能,让grep命令在容器初始化的过程中保持循环。 - Mr-Programs
有关于 docker logs 输出到标准输出和标准错误的更多信息,请参考:https://github.com/moby/moby/issues/41139 - cdalxndr
11个回答

349
如果容器将日志记录到stderr,就会发生这种情况,管道只适用于stdout,所以请尝试:
docker logs nginx 2>&1 | grep "127."

"2>&1"会告诉shell将stderr重定向到stdout "|"使用管道将"统一"的输出传递给grep

我想知道 docker logs 命令本身是将日志打印到 stderr 而不是 stdout。 - Code-Apprentice

38

作为vim的粉丝,我更喜欢使用less并使用/进行搜索(或向后搜索使用?)

docker logs nginx 2>&1 | less  

有关vim搜索的更多信息,请在这里查看。


12
可以使用docker logs nginx |& less来减少输入字符数。 - Milad ABC

14
docker logs <container_name> 2>&1 | grep <string>

12
此外,我发现在日志中突出显示一些术语很有用。特别是在生成大量日志输出的生产安装中。在我的情况下,我想突出显示COUNT(*)语句。但是,使用简单的grep无法看到整个多行SQL语句。这是可能的使用-E开关和一些正则表达式
例如,以下代码段搜索包含COUNT(*)count(*)的所有查询:
docker logs <containerName> -f | grep --line-buffered -i -E --color "select count\(\*\)|$"

一些解释:

  • docker logs -f 告诉 docker 跟随日志,因此过滤器也适用于新条目,例如使用 tail -f 查看时
  • grep 的 --line-buffered 开关在每行刷新输出,这是实时 grep 时需要的,当使用 docker logs -f
  • -E 是一个扩展正则表达式模式,需要应用我们的模式,以允许我们返回不匹配的结果
  • --color 高亮匹配的部分(在我的 Ubuntu 16.04 LTS 上似乎是默认行为,但可能在其他发行版上不是,因此我在这里包含它以确保安全)
  • * 被转义以禁用其 特殊的 glob 功能,其中 () 被掩盖以避免它们作为组的正则表达式含义,该功能由 -E 开关启用
如果容器将日志输出到stderr,您可以将它们像Edoardo已经为简单的grep编写的那样进行管道传输:
docker logs <containerName> -f 2>&1 | grep --line-buffered -i -E --color "select count\(\*\)|$"

如果不需要实时grep,可以省略-f开关。在两种情况下,您都可以看到整个日志,但是高亮显示搜索词,如下所示:

enter image description here


11

您还可以使用匿名管道

docker logs nginx 2> >(grep '127.')

1
由于某种原因,这是唯一对我有效的答案。其他的都不行,我说不清楚为什么。似乎 docker logs 直接写入屏幕,绕过了 STDOUT 或 STDERR。 - Anne van Leyden

10

您可以使用以下内容:

  1. On all shells:
    docker logs nginx 2>&1 | grep "127."
    
  2. Only on newer versions of bash works:
    docker logs nginx | &> grep "127"
    

这是什么语法?

  • 标准输入 (0)
  • 标准输出 (1)
  • 标准错误 (2)

> 运算符实际上默认使用 1 作为文件描述符编号,这就是为什么我们不需要指定 1> 来重定向标准输出:(date 1> now.txt)= (date > now.txt)

一起来

我们可以同时重定向多个流!在这个例子中,我们连接了两个文件,将标准输出重定向到一个名为insects.txt的文件中,并将标准错误重定向到一个名为error.txt的文件中。

cat bees.txt ants.txt > insects.txt 2> error.txt
变得花哨起来

如果我们想要将标准输出和标准错误都重定向到同一个文件,我们可以使用ls docs > output.txt 2> output.txt

或者我们可以使用2>&1,这是一种花哨的语法,意思是"将标准错误重定向到与标准输出相同的位置。"

ls docs > output.txt 2>&1
变得更加高级

Bash的新版本还支持更加高级的语法来将标准输出和标准错误都重定向到同一个文件中,使用&>符号。

ls docs &> output.txt

7

对于那些遇到这个问题的人,以下是对评论进行跟进并澄清的最简单方法。这是我能想到的搜索nginx容器日志的最简单方法。

docker logs nginx > stdout.log 2>stderr.log
cat stdout.log | grep "127."

在我看来,这有点混乱,因为你需要创建和删除这些可能非常大的文件。希望我们能获得一些工具来使它更加方便。


1
不太可能 - docker logs 看起来不支持单独的 stdout 和 stderr。 - Martynas Jusevičius

6

通常在调试问题时,我也会使用-f选项。

docker logs -f nginx 2>&1 | grep "127."

它将实时显示我们期望的内容。

如果要包括时间戳,请添加“-t”。

docker logs -ft nginx 2>&1 | grep "127."

4
运行以下命令以提取镜像nginx的容器名称 -
docker ps --filter ancestor=nginx

从上一个命令中复制容器 ID,然后通过以下命令提取容器的日志路径

grep "127." `docker inspect --format={{.LogPath}} <ContainerName>`

1

首先,使用以下命令(b1e3c456f07f是容器id):

docker inspect --format='{{.LogPath}}' b1e3c456f07f

结果将类似于以下内容:
/var/lib/docker/containers/b1e3c456f07f2cb3ae79381ada33a034041a10f65174f52bc1792110b36fb767/b1e3c456f07f2cb3ae79381ada33a034041a10f65174f52bc1792110b36fb767-json.log

其次,使用以下命令(如果您喜欢,可以使用vim):

nano /var/lib/docker/containers/b1e3c456f07f2cb3ae79381ada33a034041a10f65174f52bc1792110b36fb767/b1e3c456f07f2cb3ae79381ada33a034041a10f65174f52bc1792110b36fb767-json.log

应该是 grep /var/lib/docker/... '127.' 而不是 nano,对吗? - karlsebal
OC。你甚至可以使用MS Word或将其发送到打印机;) 至少你应该给出如何搜索字符串的建议,因为这是要解决的任务。 - karlsebal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接