Jason Koo

      Stay hungry, Stay foolish!

导航

How to fix stdio buffering

Posted on 2013-10-30 15:23  Jason Koo  阅读(243)  评论(0编辑  收藏  举报

It’s a common problem. You write some shell command like:

$ tail -f /var/log/foo | egrep -v 'some|stuff' | sed | awk

and wonder why nothing is printed, even though you know some text has matched. The problem is that stdio is being buffered, and there’s a very good write-up of the problem here so I won’t repeat the technical background.

What I will provide though is how to fix it for common cases.

stdbuf

stdbuf is part of GNU coreutils, and is essentially an LD_PRELOAD hack which calls setvbuf() for an application. Thus it is a generic solution to the problem and can be used to fix most applications. Usage looks like this:

$ tail -f /var/log/foo | stdbuf -o0 app ...

which will disable output buffering for app, assuming it does not do something itself to reverse thesetvbuf() call. An example of a misbehaving application is mawk, below.

awk

GNU awk needs no modifications, that is it does not buffer when there is no controlling tty.

mawk however (the default awk in Debian/Ubuntu and possibly others) buffers output, and also does not seem to work with stdbuf. It does however provide a -Winteractive option which will turn off buffering.

$ tail -f /var/log/foo | gawk

or

$ tail -f /var/log/foo | mawk -Winteractive

sed

GNU sed provides the -u option which calls fflush(), thereby providing unbuffered output. You can also use stdbuf as above.

$ tail -f /var/log/foo | sed -u

or

$ tail -f /var/log/foo | stdbuf -o0 sed

grep

Similar to sed, GNU grep provides a specific option, --line-buffered, to disable buffering, or again you can use stdbuf.

$ tail -f /var/log/foo | grep --line-buffered

or

$ tail -f /var/log/foo | stdbuf -o0 grep

This article is copied from http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html.