Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a script which calls two commands:

long_running_command | print_progress

The long_running_command prints a progress but I'm unhappy with it. I'm using print_progress to make it more nice (namely, I print the progress in a single line).

The problem: The pipe activates a 4K buffer, to the nice print program gets nothing ... nothing ... nothing ... a whole lot ... :)

How can I disable the 4K buffer for the long_running_command (no, I don't have the source)?

share|improve this question

migrated from stackoverflow.com Nov 25 '11 at 22:03

This question came from our site for professional and enthusiast programmers.

So when you run long_running_command without piping you can see the progress updates properly, but when piping they get buffered? – second Jun 16 '09 at 10:58
Yes, that's exactly what happens. – Aaron Digulla Jun 16 '09 at 11:50
The inability for a simple way of controlling buffering has been a problem for decades. For example, see: marc.info/?l=glibc-bug&m=98313957306297&w=4 which basicly says "I can't be arsed doing this and here's some clap-trap to justify my position" – Adrian Pronk Oct 19 '10 at 21:59
serverfault.com/a/589614/67097 – Nakilon Feb 9 '15 at 9:08

11 Answers 11

up vote 137 down vote accepted

You can use the expect command unbuffer, e.g.

unbuffer long_running_command | print_progress

unbuffer connects to long_running_command via a pseudoterminal (pty), which makes the system treat it as an interactive process, therefore not using the 4-kiB buffering in the pipeline that is the likely cause of the delay.

For longer pipelines, you may have to unbuffer each command (except the final one), e.g.

unbuffer x | unbuffer -p y | z
share|improve this answer
In fact, the use of a pty to connect to interactive processes is true of expect in general. – cheduardo Jun 17 '09 at 7:58
When pipelining calls to unbuffer, you should use the -p argument so that unbuffer reads from stdin. – Chris Conway Oct 6 '09 at 20:18
Note: On debian systems, this is called expect_unbuffer and is in the expect-dev package, not the expect package – bdonlan Jan 24 '11 at 11:14
@bdonlan: At least on Ubuntu (debian-based), expect-dev provides both unbuffer and expect_unbuffer (the former is a symlink to the latter). The links are available since expect (2009). – J.F. Sebastian Apr 11 '13 at 13:00
The link for "unbuffer" is dead – qdii May 12 '13 at 11:38

Another way to skin this cat is to use the stdbuf program, which is part of the GNU Coreutils (FreeBSD also has its own one).

stdbuf -i0 -o0 -e0 command

This turns off buffering completely for input, output and error. For some applications, line buffering may be more suitable for performance reasons:

stdbuf -oL -eL command

Note that it only works for stdio buffering (printf(), fputs()...) for dynamically linked applications, and only if that application doesn't otherwise adjust the buffering of its standard streams by itself, though that should cover most applications.

share|improve this answer
Why doesn’t this get more upvotes? it's a better solution imho. Does it have any downsides? – qdii May 12 '13 at 11:39
"unbuffer" needs to be installed in Ubuntu, which is inside the package: expect-dev which is 2MB... – lepe Jun 27 '13 at 6:21
@qdii stdbuf does not work with tee, because tee overwrites the defaults set by stdbuf. See the manual page of stdbuf. – ceving Jun 30 '14 at 11:51
@lepe Bizarrely, unbuffer has dependencies on x11 and tcl/tk, meaning it actually needs >80 MB if you're installing it on a server without them. – jpatokal Aug 28 '14 at 12:27
@qdii stdbuf uses LD_PRELOAD mechanism to insert its own dynamically loaded library libstdbuf.so. This means that it will not work with these kinds executables: with setuid or file capabilities set, statically linked, not using standard libc. In these cases it is better to use the solutions with unbuffer / script / socat. See also stdbuf with setuid/capabilities. – pabouk Oct 12 '15 at 9:20

Yet another way to turn on line-buffering output mode for the long_running_command is to use the script command that runs your long_running_command in a pseudo terminal (pty).

script -q /dev/null long_running_command | print_progress      # FreeBSD, Mac OS X
script -c "long_running_command" /dev/null | print_progress    # Linux
share|improve this answer
+1 nice trick, since script is such an old command, it should be available on all Unix-like platforms. – Aaron Digulla Jan 20 '13 at 13:01
you also need -q on Linux: script -q -c 'long_running_command' /dev/null | print_progress – J.F. Sebastian Apr 11 '13 at 12:51
It seems like script reads from stdin, which makes it impossible to run such a long_running_command in the background, at least when started from interactive terminal. To workaround, I was able to redirect stdin from /dev/null, since my long_running_command doesn't use stdin. – haridsv Nov 15 '13 at 12:44
Even works on Android. – user1147688 Jul 2 '14 at 23:36
I can confirm that this also works on Mac – Umur Kontacı May 17 '15 at 23:22

If it is a problem with the libc modifying its buffering / flushing when output does not go to a terminal, you should try socat. You can create a bidirectional stream between almost any kind of I/O mechanism. One of those is a forked program speaking to a pseudo tty.

 socat EXEC:long_running_command,pty,ctty STDIO 

What it does is

  • create a pseudo tty
  • fork long_running_command with the slave side of the pty as stdin/stdout
  • establish a bidirectional stream between the master side of the pty and the second address (here it is STDIO)

If this gives you the same output as long_running_command, then you can continue with a pipe.

Edit : Wow Did not see the unbuffer answer ! Well, socat is a great tool anyway, so I might just leave this answer

share|improve this answer
...and I didn't know about socat - looks kinda like netcat only perhaps more so. ;) Thanks and +1. – cheduardo Jun 20 '09 at 9:32
+1 for explaining the reason behind the buffering! – musiphil Feb 8 '14 at 7:55
I'd use socat -u exec:long_running_command,pty,end-close - here – Stéphane Chazelas Aug 7 '15 at 13:10

For grep, sed and awk you can force output to be line buffered. You can use:

grep --line-buffered

Force output to be line buffered.  By default, output is line buffered when standard output is a terminal and block buffered other-wise.

sed -u

Make output line buffered.

See this page for more information: http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html

share|improve this answer

It used to be the case, and probably still is the case, that when standard output is written to a terminal, it is line buffered by default - when a newline is written, the line is written to the terminal. When standard output is sent to a pipe, it is fully buffered - so the data is only sent to the next process in the pipeline when the standard I/O buffer is filled.

That's the source of the trouble. I'm not sure whether there is much you can do to fix it without modifying the program writing into the pipe. You could use the setvbuf() function with the _IOLBF flag to unconditionally put stdout into line buffered mode. But I don't see an easy way to enforce that on a program. Or the program can do fflush() at appropriate points (after each line of output), but the same comment applies.

I suppose that if you replaced the pipe with a pseudo-terminal, then the standard I/O library would think the output was a terminal (because it is a type of terminal) and would line buffer automatically. That is a complex way of dealing with things, though.

share|improve this answer

You can use

long_running_command 1>&2 |& print_progress

The problem is that libc will line-buffer when stdout to screen, and full-buffer when stdout to a file. But no-buffer for stderr.

I don't think it's the problem with pipe buffer, it's all about libc's buffer policy.

share|improve this answer
You're right; my question is still: How can I influence libc's buffer policy without recompiling? – Aaron Digulla Apr 4 '14 at 8:55
@StéphaneChazelas fd1 will redirected to stderr – Wang HongQin Aug 7 '15 at 9:26
@StéphaneChazelas i dont get your arguing point. plz do a test, it works – Wang HongQin Aug 7 '15 at 9:53
OK, what's happening is that with both zsh (where |& comes from adapted from csh) and bash, when you do cmd1 >&2 |& cmd2, both fd 1 and 2 are connected to the outer stdout. So it works at preventing buffering when that outer stdout is a terminal, but only because the output doesn't go through the pipe (so print_progress prints nothing). So it's the same as long_running_command & print_progress (except that print_progress stdin is a pipe that has no writer). You can verify with ls -l /proc/self/fd >&2 |& cat compared to ls -l /proc/self/fd |& cat. – Stéphane Chazelas Aug 7 '15 at 10:44
That's because |& is short for 2>&1 |, literally. So cmd1 |& cmd2 is cmd1 1>&2 2>&1 | cmd2. So, both fd 1 and 2 end up connected to the original stderr, and nothing is left writing to the pipe. (s/outer stdout/outer stderr/g in my previous comment). – Stéphane Chazelas Aug 7 '15 at 10:48

I don't think the problem is with the pipe. It sounds like your long running process is not flushing its own buffer frequently enough. Changing the pipe's buffer size would be a hack to get round it, but I don't think its possible without rebuilding the kernel - something you wouldn't want to do as a hack, as it probably aversley affect a lot of other processes.

share|improve this answer
The root cause is that libc switches to 4k buffering if the stdout is not a tty. – Aaron Digulla Jun 16 '09 at 11:50
That is very interesting ! because pipe don't cause any buffering. They provide buffering, but if you read from a pipe, you get whatever data is available, you don't have to wait for a buffer in the pipe. So the culprit would be the stdio buffering in the application. – shodanex Jun 16 '09 at 13:58

I know this is an old question and already had lot of answers, but if you wish to avoid the buffer problem, just try something like:

stdbuf -oL tail -f /var/log/messages | tee -a /home/your_user_here/logs.txt

This will output in real time the logs and also save them into the logs.txt file and the buffer will no longer affect the tail -f command.

share|improve this answer
This looks like the second answer :-/ – Aaron Digulla Aug 11 '15 at 11:17
stdbuf is included in gnu coreutils(I verified on latest version 8.25). verified this works on an embedded linux. – zhaorufei Jul 20 at 10:18

According to this the pipe buffer size seems to be set in the kernel and would require you to recompile your kernel to alter.

share|improve this answer
I believe that is a different buffer. – Samuel Edwin Ward Jan 8 '13 at 21:58

According to this post here, you could try reducing the pipe ulimit to one single 512-byte block. It certainly won't turn off buffering, but well, 512 bytes is way less than 4K :3

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.