Skip to main content
added a few more alternatives tested
Source Link
PLL
  • 1k
  • 7
  • 21

I’m trying to use stdbuf to control buffering for a process in terminal — specifically, using stdbuf -o0 to prevent buffering when piping output onward, roughly as described in this answer — but it doesn’t seem to work as expected, or indeed have any effect. Compare the output of the following commands:

{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo'
{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o0 grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o1M grep 'oo'

In the first, grep processes and outputs each line as it’s received. In the second, the output appears all together after 2 seconds — as explained here, grep buffers its output when not outputting to a terminal. Both of these are as expected. The third one is the surprise: according to the first linked answer and all other documentation/discussion I can find, stdbuf -o0 should prevent grep buffering its output, so that this ends up acting like the first command. However, on my Macs it acts like the second command — output arrives all together after 2 seconds. Similarly, the fourth command should (as I understand) cause grep to buffer its output, and so act like the second — but it doesn’t, it gives incremental output like the first.

Why is stdbuf not having any effect here — do other Mac users get the same results? Is And is there anotheran altnernative way to generally prevent buffering in pipes? I’ve tried stdbuf -oL (line buffering), and this similarly doesn’t have any effect. I’ve also tried with gstdbuf, i.e. the version installed by Homebrew’s coreutils, and that also has no effect; both stdbuf and gstdbuf are version 9.5. I’ve tried this on three Macs, variously running Sonoma 14.4.1 and Ventura 13.6.6, and Monterey 12.7.4, with identical results. The I’ve tried unbuffer from the expect package; that doesn’t have any effect here either. And I’ve tried with other pipeline targets besides cat; they all seem to show the same behaviour.

The grep-specific option grep --line-buffered does work, as does replacing grep by ag, which doesn’t buffer for pipes by default. However, my actual current use-case is with ripgrep-all (rga) which buffers in pipelines like grep but doesn’t offer a nonline-buffering or linenon-buffering flagoption, and itthis seems to be a general issue with stdbuf and unbuffer (I can’t find any test in which it seemsthey seem to have any effect), so I’d really like to find a general answer if possible.

I’m trying to use stdbuf to control buffering for a process in terminal — specifically, using stdbuf -o0 to prevent buffering when piping output onward, roughly as described in this answer — but it doesn’t seem to work as expected, or indeed have any effect. Compare the output of the following commands:

{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo'
{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o0 grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o1M grep 'oo'

In the first, grep processes and outputs each line as it’s received. In the second, the output appears all together after 2 seconds — as explained here, grep buffers its output when not outputting to a terminal. Both of these are as expected. The third one is the surprise: according to the first linked answer and all other documentation/discussion I can find, stdbuf -o0 should prevent grep buffering its output, so that this ends up acting like the first command. However, on my Macs it acts like the second command — output arrives all together after 2 seconds. Similarly, the fourth command should (as I understand) cause grep to buffer its output, and so act like the second — but it doesn’t, it gives incremental output like the first.

Why is stdbuf not having any effect here? Is there another way to generally prevent buffering in pipes? I’ve tried stdbuf -oL (line buffering), and this similarly doesn’t have any effect. I’ve also tried with gstdbuf, i.e. the version installed by Homebrew’s coreutils, and that also has no effect; both stdbuf and gstdbuf are version 9.5. I’ve tried this on three Macs, variously running Sonoma 14.4.1 and Ventura 13.6.6, and Monterey 12.7.4, with identical results. The grep-specific option grep --line-buffered does work, as does replacing grep by ag, which doesn’t buffer for pipes by default. However, my actual current use-case is with ripgrep-all (rga) which doesn’t offer a non-buffering or line-buffering flag, and it seems to be a general issue with stdbuf (I can’t find any test in which it seems to have any effect), so I’d really like to find a general answer if possible.

I’m trying to use stdbuf to control buffering for a process in terminal — specifically, using stdbuf -o0 to prevent buffering when piping output onward, roughly as described in this answer — but it doesn’t seem to work as expected, or indeed have any effect. Compare the output of the following commands:

{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo'
{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o0 grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o1M grep 'oo'

In the first, grep processes and outputs each line as it’s received. In the second, the output appears all together after 2 seconds — as explained here, grep buffers its output when not outputting to a terminal. Both of these are as expected. The third one is the surprise: according to the first linked answer and all other documentation/discussion I can find, stdbuf -o0 should prevent grep buffering its output, so that this ends up acting like the first command. However, on my Macs it acts like the second command — output arrives all together after 2 seconds. Similarly, the fourth command should (as I understand) cause grep to buffer its output, and so act like the second — but it doesn’t, it gives incremental output like the first.

Why is stdbuf not having any effect here — do other Mac users get the same results? And is there an altnernative way to generally prevent buffering in pipes? I’ve tried stdbuf -oL (line buffering), and this similarly doesn’t have any effect. I’ve also tried with gstdbuf, i.e. the version installed by Homebrew’s coreutils, and that also has no effect; both stdbuf and gstdbuf are version 9.5. I’ve tried this on three Macs, variously running Sonoma 14.4.1 and Ventura 13.6.6, and Monterey 12.7.4, with identical results. I’ve tried unbuffer from the expect package; that doesn’t have any effect here either. And I’ve tried with other pipeline targets besides cat; they all seem to show the same behaviour.

The grep-specific option --line-buffered does work, as does replacing grep by ag, which doesn’t buffer for pipes by default. However, my actual use-case is with ripgrep-all (rga) which buffers in pipelines like grep but doesn’t offer a line-buffering or non-buffering option, and this seems to be a general issue with stdbuf and unbuffer (I can’t find any test in which they seem to have any effect), so I’d really like to find a general answer if possible.

edited tags
Link
bmike
  • 241.3k
  • 80
  • 433
  • 958
Source Link
PLL
  • 1k
  • 7
  • 21

How to control buffering for processes in terminal pipe? `stdbuf` doesn’t seem to work

I’m trying to use stdbuf to control buffering for a process in terminal — specifically, using stdbuf -o0 to prevent buffering when piping output onward, roughly as described in this answer — but it doesn’t seem to work as expected, or indeed have any effect. Compare the output of the following commands:

{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo'
{ echo 'foo' ; sleep 2 ; echo 'boo'} | grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o0 grep 'oo' | cat
{ echo 'foo' ; sleep 2 ; echo 'boo'} | stdbuf -o1M grep 'oo'

In the first, grep processes and outputs each line as it’s received. In the second, the output appears all together after 2 seconds — as explained here, grep buffers its output when not outputting to a terminal. Both of these are as expected. The third one is the surprise: according to the first linked answer and all other documentation/discussion I can find, stdbuf -o0 should prevent grep buffering its output, so that this ends up acting like the first command. However, on my Macs it acts like the second command — output arrives all together after 2 seconds. Similarly, the fourth command should (as I understand) cause grep to buffer its output, and so act like the second — but it doesn’t, it gives incremental output like the first.

Why is stdbuf not having any effect here? Is there another way to generally prevent buffering in pipes? I’ve tried stdbuf -oL (line buffering), and this similarly doesn’t have any effect. I’ve also tried with gstdbuf, i.e. the version installed by Homebrew’s coreutils, and that also has no effect; both stdbuf and gstdbuf are version 9.5. I’ve tried this on three Macs, variously running Sonoma 14.4.1 and Ventura 13.6.6, and Monterey 12.7.4, with identical results. The grep-specific option grep --line-buffered does work, as does replacing grep by ag, which doesn’t buffer for pipes by default. However, my actual current use-case is with ripgrep-all (rga) which doesn’t offer a non-buffering or line-buffering flag, and it seems to be a general issue with stdbuf (I can’t find any test in which it seems to have any effect), so I’d really like to find a general answer if possible.