> On Sun, 21 Apr 2024, wrotycz wrote: > > > > It seems that it's 'interleaved' when buffer is written to a file or > > pipe, and because stdout is buffered it waits until buffer is full or > > flushed, while stderr is not and it doesn't wait and write immediately. > > Right; my point was just that stdout and stderr are still separate streams > (with distinct buffers & buffering modes), even if fd 1 & 2 refer to the > same pipe.
As I guess I should've expected, the behavior differs between a bash script and a compiled program. $ cat ./abc123 #!/bin/bash printf '%s' 'a' >&2 printf '%s' '1' printf '%s' 'b' >&2 printf '%s' '2' printf '%s' 'c' >&2 printf '%s' '3' printf '\n' >&2 printf '\n' exit 0; $ ./abc123 a1b2c3 $ ./abc123 2>&1 | cat a1b2c3 $ cat ./abc123.c #include <stdio.h> int main() { putc('a', stderr); putc('1', stdout); putc('b', stderr); putc('2', stdout); putc('c', stderr); putc('3', stdout); putc('\n', stderr); putc('\n', stdout); return 0; } $ gcc -o abc123.exe abc123.c $ ./abc123.exe a1b2c3 $ ./abc123.exe 2>&1 | cat 123 abc $ stdbuf --output=0 --error=0 -- ./abc123.exe 2>&1 | cat 123 abc $ I probably shouldn't go around assuming that things are smart. I'll accept that adding logic to glibc to test if any given set of file descriptors are pointing to the same file or pipe and ensuring that anything written to any one of those file descriptors is always actually written to the stream for the first one, for instance, would probably be overkill.