Why pipes sometimes get "stuck": buffering #958
Labels
CLI-UX
Command Line Interface user experience and best practices
linux
Linux notes tools links
shell-tools
Tools and utilities for shell scripting and command line operations
TIL
Short notes or tips on coding, linux, llms, ml, etc
Why pipes sometimes get "stuck": buffering
Snippet
Why this happens: buffering
The reason why "pipes get stuck" sometimes is that it's VERY common for programs to buffer their output before writing it to a pipe or file. This is for performance reasons: writing all output immediately as soon as you can uses more system calls, so it's more efficient to save up data until you have 8KB or so of data to write (or until the program exits) and THEN write it to the pipe.
In this example:
the problem is that
grep thing1
is saving up all of its matches until it has 8KB of data to write, which might literally never happen.Programs don't buffer when writing to a terminal, but they do buffer when writing to a pipe. This is because the way grep (and many other programs) decides to buffer its output depends on whether it's writing to a terminal or not.
Commands that buffer & commands that don't
Some commands that don't buffer their output:
tail
cat
tee
But most other commands will buffer their output when writing to a pipe, including:
grep
(--line-buffered
)sed
(-u
)awk
(there's afflush()
function)tcpdump
(-l
)jq
(-u
)tr
(-u
)cut
(can't disable buffering)Programming languages where the default "print" statement buffers
The default
print
statement will buffer output when writing to a pipe in languages like:setvbuf
)python -u
,PYTHONUNBUFFERED=1
,sys.stdout.reconfigure(line_buffering=False)
, orprint(x, flush=True)
)STDOUT.sync = true
)$| = 1
)Solutions to avoid buffering
cat /some/log/file | grep thing1 | grep thing2 | tail
grep
:tail -f /some/log/file | grep --line-buffered thing1 | grep thing2
awk
instead of multiplegrep
s:tail -f /some/log/file | awk '/thing1/ && /thing2/'
stdbuf
to disable libc buffering:tail -f /some/log/file | stdbuf -o0 grep thing1 | grep thing2
unbuffer
to force the program's output to be a TTY:tail -f /some/log/file | unbuffer grep thing1 | grep thing2
Task
Take the user input and reformat it according to the instructions.
Suggested Labels
Suggested labels
None
The text was updated successfully, but these errors were encountered: