day0ops
day0ops

Reputation: 7492

pipe and grep in Docker container seems to get blocked

I have a simple bash script as follows that is part of a docker image.

test.sh,

#!/bin/bash

set -e

logit() {
    log_date=`date +"%F %T"`
    echo "[$log_date][INFO] $1"
}

waitForServerToStart() {
    while true; do
        logit "Testing .... 1"
        netstat -anpt
        logit "Testing .... 2"
        netstat -anpt | grep tcp
        logit "Testing .... 3"
        sleep 5
        logit "Testing .... 4"
    done
}

waitForServerToStart

run.sh,

#!/bin/sh

/test.sh &

# Run forever
while true; do sleep 5; done

Dockerfile,

FROM openjdk:8u191-jre-alpine3.9

COPY files/run.sh /
COPY files/test.sh /

CMD ["/run.sh"]

If I run this container I only get the following output which leads me to believe somehow grep and "pipe" seem to get blocked.

[2019-03-06 11:10:45][INFO] Testing .... 1
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 172.17.0.2:58278        xxx.xxx.xx.xx:443     FIN_WAIT2   -
[2019-03-06 11:10:45][INFO] Testing .... 2 

Can someone please shed some light around this ?

It works fine If I comment out netstat -anpt | grep tcp. I would then see the subsequent log lines and it would also continue in the loop.

[2019-03-06 11:25:36][INFO] Testing .... 3
[2019-03-06 11:25:41][INFO] Testing .... 4

Upvotes: 2

Views: 785

Answers (1)

Andreas Lorenzen
Andreas Lorenzen

Reputation: 4230

This one has me puzzled! But I have a solution for you:

Use awk instead of grep

In test.sh use this instead:

netstat -anpt | awk /tcp/

So that the file looks like this:

#!/bin/bash

set -e

logit() {
    log_date=`date +"%F %T"`
    echo "[$log_date][INFO] $1"
}

waitForServerToStart() {
    while true; do
        logit "Testing .... 1"
        netstat -anpt
        logit "Testing .... 2"
        netstat -anpt | awk /tcp/
        logit "Testing .... 3"
        sleep 5
        logit "Testing .... 4"
    done
}

waitForServerToStart

For a reason that I cannot explain - grep will not return when reading from the pipe when invoked from the script. I created your container locally, ran it and entered it - and the command netstat -anpt | grep tcp runs just fine and exits. If you replace it with netstat -anpt | cat in your test.sh script, then it will also pass just fine.

I looked all over the place for the someone with an identical issue with grep in a container from the distro you are using, the version etc. - but came up empty handed.

I believe that it may have to do with grep waiting for a EOF character that never lands - but I am not sure.

Upvotes: 2

Related Questions