stdio Buffering

1 minute read

Updated:

What is line buffering

Programs can choose to buffer IO for performance. Reading/writing large chunks at once is more efficient than reading/writing single characters. For interactive input, it’s often desirable to remove line buffering, so that data can stream in realtime. Many programs will change line buffering behaviour, depending on whether the input or output is interactive (tty).

But sometimes, programs are not written well. So we want a solution to avoid line-buffering.

stdbuf

stdbuf comes standard on linux systems. it allows modifying the input/output stream buffering behaviour.

The following example has a program generating infinite output, piped to grep (further piped to cat to force grep into non-tty mode). Note that grep has --line-buffered argument for enabling line buffering, instead of block-buffering.

fish -c 'while echo hi; sleep 0.5; end' | grep -Pi --color=auto 'hi' | cat
fish -c 'while echo hi; sleep 0.5; end' | stdbuf --output=0 grep -Pi --color=auto 'hi' | cat

The first command will hang and buffer, which will make it seems like the grep command isn’t finding anything. When ctrl-c, stdout is flushed and all the results are dumped on the screen.

The second command uses stdbuf with output set to unbuffered, which will print the output immediately. The buffering amount can also be manually set to a value of how many bytes to output.

Alternatives

unbuffer is a tool that wraps expect. expect creates a pseudo-tty that it uses to watch for prompts and automate macros via stdin. unbuffer is specific use-case of expect, where there are no rules to match and react, it’s only used to set up the psuedo-tty. This tricks the pipeline into line-buffering mode.