As part of a script that I was writing today I was attempting to count the number of times that a containerised Liberty server had started. I started with the following command:
1 |
docker logs test | grep "CWWKF0011I" | wc -l |
(where CWWKF0011I is the code for Liberty’s “ready to run a smarter planet” message) but it was giving me an answer one greater than I anticipated. Stripping off the line count at the end quickly showed why: in addition to the messages that I was expecting, grep also appeared to be returning an error message from the logs. It took me a little while longer to get my head around what was going on. grep wasn’t passing the error at all. Indeed, the error wasn’t even getting as far as grep. Instead, docker logs was trying to be helpful and recreating the stdout and stderr streams from the container; stdout was getting piped to grep, and stderr, where Liberty was outputting its error message, was just going straight to the console. This was also going to cause me a headache elsewhere when I was actually trying to grep for errors.
When I first learnt bash, 2>&1 was the way to redirect stderr to stdout but, just to prove that you can teach an old dog new tricks, here’s the working version of my original command using the Bash 4 syntactic sugar to merge stderr in to a pipe:
1 |
docker logs test |& grep "CWWKF0011I" | wc -l |
As a further aside (which certainly added to my confusion when trying to debug this), if you allocate a TTY to a container via the -t flag on the run command, stderr will be merged in to stdout before it hits the logs so you won’t see this behaviour at all!
[…] of the file so that entries output whilst the startServer.sh script is running are not lost. As previously noted, Docker preserves stderr across the remote API so we make sure to direct the output from […]