Reputation: 444
I am running a python script which produces certain output when I run it in verbose mode. When I pipe the output to the less utility, the output is in a different order. For reference, the script is, if not exactly, very nearly this:
http://svn.apache.org/repos/asf/subversion/trunk/tools/client-side/change-svn-wc-format.py
Specifically, I get the "Data for the following field(s)" message and when I run it without piping the output to less, this message appears last. When I pipe the output to less, the output mysteriously appears first.
Can anybody explain this?
I have determined that the error message goes to stderr while the verbose messages go to stdout. However, even when I do:
./svnfixversion ./ 1.5 --verbose 2>&1 | less
the output is different from when I just leave off the | less. If the stderr is getting redirected to stdout, shouldn't less preserve the order?
Upvotes: 0
Views: 112
Reputation: 136296
When you run:
./svnfixversion ./ 1.5 --verbose
its stdout
is line buffered, stderr
is non-buffered.
In:
./svnfixversion ./ 1.5 --verbose 2>&1 | less
its stdout
is fully buffered, stderr
is non-buffered.
The buffering mode of ./svnfixversion
FILE* stdout
is what makes the output different in these two cases.
If you want the second output to be identical to the first one, set stdout
buffering mode to line buffered with stdbuf
application:
stdbuf --output=L ./svnfixversion ./ 1.5 --verbose 2>&1 | less
In modern bash
you can replace 2>&1 |
with shorter |&
.
What happens under the hood, is that at program start before main()
is called glibc
calls isatty(STDOUT_FILENO)
to determine whether stdout
is connected to a terminal. If so, stdout
is line buffered, otherwise full buffered. stderr
is always unbuffered.
Upvotes: 3