unbuffer

unbuffer is a small utility from the Expect distribution that disables the output buffering programs apply when their stdout is redirected into a pipe. See the unbuffer(1) man page.

The problem

C stdio chooses a buffering strategy based on where stdout points: line-buffered when attached to a terminal (flush on every newline), but fully buffered (4–8 KB blocks) when attached to a pipe or file. The result is the classic annoyance of piping a long-running command through tee to watch progress and save a log — and seeing nothing for minutes at a time because the output is sitting in the child’s buffer. 1

Usage

unbuffer $APPLICATION | tee $LOG

unbuffer runs the command attached to a pseudo-terminal, so the child believes it is interactive and flushes per line; the pty’s output is then forwarded down the pipe in real time. 2

Alternatives

  • stdbuf -oL $APP — injects LD_PRELOAD to force line buffering in the child; lighter than a pty but only affects programs using C stdio (not, e.g., some statically linked Go binaries). See ld-preload-trick for the underlying mechanism.
  • Application flags — some tools have their own switch: grep --line-buffered, python -u (unbuffered; see python), tcpdump -l.
  • script -c "$APP" /dev/null | tee $LOG — same pty trick via util-linux script(1), no Expect dependency.

Caveat: because unbuffer allocates a pty, the child may also enable other interactive behaviors (color output, progress bars, pagers). That is usually what you want for live logs, but it can pollute machine-read output.

Sources

See also

Footnotes

  1. unbuffer(1) — Linux man page

  2. unbuffer(1) — Linux man page