Home / Alt manpages / stdbuf(1)

  • stdbuf(1)
  • User command
  • linux

Make Piped Commands Respond Promptly with stdbuf

stdbuf changes a command's standard input, output or error buffering without touching its source code. A log-tailing pipeline that only prints in bursts every few kilobytes is usually not broken, it is just fully buffered, and getting the buffering right makes it show records as they arrive instead. The examples use GNU coreutils 9.4, installed here as Ubuntu package version 9.4-3ubuntu6.3.

Allow about ten minutes. You need a shell, the coreutils package and a command whose stream buffering you want to adjust. These are ordinary user commands: no sudo, and nothing here changes a service or a configuration file.

1. Check the installed contract

Start by checking the binary and package version. This is read-only:

$ command -v stdbuf
/usr/bin/stdbuf
$ stdbuf --version | head -n 1
stdbuf (GNU coreutils) 9.4
$ dpkg-query -W -f='\${Package} \${Version}\n' coreutils
coreutils 9.4-3ubuntu6.3

Checkpoint

Your output should name GNU stdbuf and the version you intend to document or troubleshoot. If command -v points somewhere unexpected, stop and inspect that executable before you trust its behaviour.

2. Choose a stream and mode

Pass one or more of -i, -o and -e immediately before the command. The mode is either the value after the equals sign, or the next argument in a form such as -o L.

  • L requests line buffering. Valid for output and error, but not for standard input.
  • 0 requests an unbuffered stream.
  • A size such as 4K requests full buffering with a 4096-byte buffer. Decimal suffixes such as KB use powers of 1000; K and KiB use 1024 bytes.

For a live text pipeline, start with line-buffered output:

stdbuf -oL COMMAND ARGUMENTS...

Do not use -iL: the installed help explicitly rejects line buffering on standard input. If you need input unbuffered, reach for -i0 instead.

3. Apply line buffering in a pipeline

A typical use is putting stdbuf in front of whichever stage is holding output back. This is the form the local manpage documents directly:

tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq

Here cut flushes each output line instead of waiting for a full block. tail -f keeps following the file, while uniq drops adjacent duplicate names. Swap in a readable log file for access.log; do not create or truncate a production log just to test this.

Checkpoint

Run the pipeline against a test copy or a log you are already authorised to read. In a second terminal, append a harmless test line if changing that file is safe. You should see the matching first field arrive promptly once the complete line reaches the pipeline. Press Ctrl-C to stop tail -f; nothing persistent has changed.

The final stage matters too. If uniq is also delaying its output in your workload, give that stage its own buffering setting:

tail -f access.log | stdbuf -oL cut -d ' ' -f1 | stdbuf -oL uniq

Only do this when the downstream command is actually compatible with stdbuf. Buffering is a property of each process and stream, not of the pipe as a whole.

4. Test a mode without changing files

For a quick smoke test, run a short-lived shell command. This confirms stdbuf can start the command and that its exit status still comes through:

$ stdbuf -o0 sh -c 'printf "%s" ready'
ready$ echo "exit status: $?"
exit status: 0

The missing newline after ready is deliberate: the child printed exactly the text it was asked to. -o0 does not add newlines or otherwise change the command's output; it only changes the buffering mode for standard output.

When you want a newline for readability, make the command print one instead:

$ stdbuf -oL sh -c 'echo line-one'
line-one

Checks like these do not prove that every program honours stdbuf. They only confirm the wrapper invocation and the child's result.

5. Know the boundary: stdbuf is not universal

stdbuf changes the standard streams a command uses, but a program can override those settings itself, and then the program wins. The manpage names tee as an example that may adjust its own buffering regardless.

Some tools skip standard C streams for their input and output entirely. The local documentation names dd and cat as examples unaffected by stdbuf settings for that reason. If your command is one of these, adding stdbuf is not a fix; check that command's own options or documentation instead.

This is a common distraction trap: a pipeline can hold several processes, and adjusting one cannot force the rest to flush. Put the wrapper directly in front of whichever command is actually delaying its stream, then test each stage separately where you can.

6. Handle errors and exit statuses

stdbuf reports its own failures distinctly. Status 125 means stdbuf itself failed, status 126 means the command was found but could not be invoked, and status 127 means it could not be found at all. Otherwise, stdbuf just returns the child command's status.

Capture the status right after the command if a script needs to tell these cases apart:

stdbuf -oL /path/to/COMMAND --safe-test-argument
status=$?
echo "command status: $status"
case "$status" in
    125) echo 'stdbuf itself failed' >&2; exit 125 ;;
    126) echo 'command found but could not be invoked' >&2; exit 126 ;;
    127) echo 'command was not found' >&2; exit 127 ;;
esac
exit "$status"

Replace both placeholders with a command and argument you have already tested. Quote paths and values that might contain spaces, never pass untrusted text as an option string, and do not use a production service as your first test.

7. Treat explicit buffer sizes as a special case

Line and unbuffered modes are the useful starting points for interactive pipelines. The local manpage warns that on glibc platforms, requesting a specific buffer size (and therefore full buffering) has undefined operation. This machine uses glibc, so do not build a sized mode such as -o4K into a reliability-critical workflow without testing the exact program and platform first.

If you are investigating an existing sized invocation, record the command, coreutils version and libc environment before you change anything. A safe rollback is simply removing the stdbuf wrapper and running the original command again. If you changed a service unit, wrapper script or scheduled job outside these examples, restore the previous file from your normal configuration-management copy and restart the service only during an approved maintenance window.

Done means

  • You checked that the installed executable is GNU coreutils 9.4.
  • You selected the right stream: -o for output, -e for error and -i0 for unbuffered input.
  • You used line buffering on the pipeline stage actually delaying output.
  • You know that programs such as tee, dd and cat can override or bypass stdbuf.
  • You checked the returned status and can tell stdbuf failures apart from the child's own result.
  • You tested without changing persistent configuration, services or production data.