1

I have the following command:

sudo docker logs -f <id> | awk '/Listening on / {print $3; exit 0;}'

From what I understand, awk should find the first line that matches the pattern, print the correct column, and exit. However, this does not always happen: most the time it simply prints the correct column and hangs, although occasionally it exits correctly.

I've tried

$ sudo stdbuf -i0 -o0 -e0 docker logs ...  # hangs
$ sudo docker logs ... | cat | awk ... # hangs

In trying to produce a minimal example, I also tried making a pipe using mkfifo, and using cat foo | awk ... but that doesn't hang.

The output from docker logs -f <id> is

Listening on 172.17.0.2/16
...

and then it remains open, but doesn't write any thing else.

I don't understand what's going on--does anyone have any ideas?

4
  • Unable to replicate: for i in {10..20}; do echo $i; done | awk '{ exit 0} END { print NR}' works as apparently intended.
    – DopeGhoti
    Commented Dec 17, 2018 at 22:43
  • 1
    Similar: How to print only one match of grep when tail -f? or Grep slow to exit after finding match? or make tail -f exit on a broken pipe. Most likely awk exits but your shell is waiting for all processes in the pipeline. Commented Dec 17, 2018 at 22:44
  • Your output above indicates docker logs is emitting terminal sequences; are you certain that it isn’t when you pipe it to awk? Maybe pipe it into hexdump just to have a peek.
    – mevets
    Commented Dec 17, 2018 at 23:31
  • @mevets I assume you're referring to the syntax highlighting? StackExchange is doing that, the output is plain text.
    – flaviut
    Commented Dec 18, 2018 at 14:23

1 Answer 1

3

From man bash:

The shell waits for all commands in the pipeline to terminate before returning a value.

I don't have docker installed but maybe try this:

awk '/Listening on / {print $3; exit 0;}' <( sudo docker logs -f <id> )

Or you could try this:

sudo docker logs -f <id> | (awk '/Listening on / {print $3; exit 0;}'; pkill -P $$ )

So perhaps an explanation of what is going on would help. I'm assuming that the 'docker logs' command does not normally exit (the -f == follow?).

The original problem arises because the pipeline is not exiting on awk's termination - this is because the pipeline is still waiting on the docker program (see my extract above from the bash man page).

The pkill simply kills anything that has parent id $$ - ie at that moment, that is just docker.

Obviously, it would not be a good idea to chuck that command into background with '&' and then run other things - they would also get killed!

1
  • Yup, this is exactly it! This behavior is surprising, although not unexpected--the only way it could work otherwise is if bash sent SIGINT or SIGQUIT to the other programs in the pipe, and I've never seen that happen. Thank you!
    – flaviut
    Commented Dec 18, 2018 at 14:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .