在 alpine 与 ubuntu 上,来自 nc 管道的 grep 的不同行为

Different behaviour of grep with pipe from nc on alpine vs ubuntu

我想检查是否可以访问 Minecraft 服务器。这用作 docker 的健康检查。在 Ubuntu 上一切都很好,在高山 linux 上则不行。

这从 public 服务器请求 json 中的状态字符串:

echo -e "\x16\x00\x04\x10\x6d\x63\x2e\x65\x6c\x64\x65\x72\x63\x72\x61\x66\x74\x2e\x64\x65\x63\xdd\x01\x01\x00" | nc mc.eldercraft.de 25565

因为您可能想知道您正在测试什么,请求包含:

  1. 之后的 22 个内容字节
  2. 协议版本字节 00、04
  3. 此后
  4. 16 个主机名字节
  5. 2 个端口字节
  6. 握手字节结束
  7. 此后的 1 个内容字节
  8. 给我状态字节

如果成功,return 包含玩家数量,所以我想检查它是否在。

echo -e "\x16\x00\x04\x10\x6d\x63\x2e\x65\x6c\x64\x65\x72\x63\x72\x61\x66\x74\x2e\x64\x65\x63\xdd\x01\x01\x00" | nc mc.eldercraft.de 25565 | grep -q '"players":' && echo "ok"

问题: 为什么在 alpine 和 ubuntu 上处理 grep 这个输出的方式不同?即使我将值存储在变量中并将其回显给 grep,它也无法处理该字符串。即使我只是 grep 'players'.

见答案解释

解决方案:

我尝试在具有不同 shell/grep 变体的 Alpine 3.9 Docker 上重新创建结果,为每个测试退出并启动一个新容器,然后仔细检查。

这是我得到的:

  • Alpine 3.9、ash、BusyBox grep:不正常。
  • Alpine 3.9,bash,BusyBox grep:不正常。
  • Alpine 3.9,ash,GNU grep:好的。
  • Alpine 3.9,bash,GNU grep:好的。
  • Alpine 3.9, ash, BusyBox grep -F: OK.

所以看起来 grep 确实是差异的根本原因,以及它处理 nc 的二进制输出的方式。

使用 Alpine 3.9 和 GNU grep,如果我们省略 -q 和 echo,我们将得到以下输出:

Binary file (standard input) matches

这可能表明 GNU 和 BusyBox grep 处理二进制文件的方式不同。

浏览 BusyBox 的 grep,https://github.com/mirror/busybox/blob/master/findutils/grep.c,我们可以在 grep 的选项列表下找到以下注释:

/* ignored: -a "assume all files to be text" */
/* ignored: -I "assume binary files have no matches" */

如此仔细地估计,BusyBox grep 将始终为二进制数据(使用默认选项)给出零结果 - 这很好地解释了这种行为。

使用 -F - "fgrep mode",BusyBox grep 将按字面意思将 "players": 匹配到二进制字符流,所以这可行。