Kabanson
Kabanson

Reputation: 75

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

I want to check if a Minecraft server is reachable. This is used as a health check for docker. On Ubuntu all is fine, on alpine linux not.

This requesting the status string in json from a public server:

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

Because you maybe want to know what you are testing, the request contains of:

  1. 22 content byte after this
  2. protocol version bytes 00, 04
  3. 16 hostname bytes after this
  4. 2 port bytes
  5. end of handshake byte
  6. 1 content byte after this
  7. give me status byte

If successful the return contains amount of players, so I want to check if its in.

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"

Question: Why doesn't process grep this output on alpine and ubuntu like the same? Even if I store the value in a variable and echo this to grep it can't process this string. Even if I just grep for 'players'.

See answer for explanation

Solutions:

Upvotes: 2

Views: 2528

Answers (1)

valiano
valiano

Reputation: 18611

I tried to recreate the results on an Alpine 3.9 Docker with the different shell/grep variations, exiting and starting a new container for each test, then double checked.

Here's what I've got:

  • Alpine 3.9, ash, BusyBox grep: not OK.
  • Alpine 3.9, bash, BusyBox grep: not OK.
  • Alpine 3.9, ash, GNU grep: OK.
  • Alpine 3.9, bash, GNU grep: OK.
  • Alpine 3.9, ash, BusyBox grep -F: OK.

So it seems that grep is indeed the root cause of the difference, and the way it handles the binary output from nc.

With Alpine 3.9 and GNU grep, if we omit the -q and echo, we'll get the following output:

Binary file (standard input) matches

This could suggest that GNU and BusyBox grep may handle binary files differently.

Browsing through BusyBox's grep, https://github.com/mirror/busybox/blob/master/findutils/grep.c, we can find the following comments, under grep's options listing:

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

So carefully estimating, BusyBox grep will always give zero results for binary data (with the default options) - that well explains the behavior.

With -F - "fgrep mode", BusyBox grep will match "players": literally to the binary characters stream, so this works.

Upvotes: 2

Related Questions