In bash, I know that foo 1>a.txt 2>&1
outputs both stdout and stderr to the same file.
But, if I replace this by foo 1>a.txt 2>a.txt
, it behaves strangely.
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
A sample code is here:
#!/usr/bin/bash
function foo {
echo stdout1
echo stdout2
echo stdout3
echo stderr1 >&2
echo stderr2 >&2
echo stdout4
}
foo 1>a.txt 2>a.txt
Then, the content of a.txt is
stderr1
stderr2
stdout3
stdout4
A strange point is I would expect that stdout does not appear at all or,
behaves like 1> a.txt 2>&1
, but it is not so.
A problem is that a.txt is open in write mode twice.
I want to know what happens in this redirections.
This is an expected behavior but looks strange just because the number of characters of the English words stderr
and stdout
are same.
The root cause is a.txt
is open twice, giving bash
two file handles which both point to a.txt
. They are completely independent, meaning the seek positions are not synced.
Let's see it step by step. When
echo stdout1
echo stdout2
echo stdout3
is executed, the content of the file becomes
stdout1
stdout2
stdout3
Then
echo stderr1 >&2
echo stderr2 >&2
is executed but the seek position of stderr
is still 0
so the first and second line is overwritten, giving
stderr1
stderr2
stdout3
Finally,
echo stdout4
gives
stderr1
stderr2
stdout3
stdout4
because the seek position of stdout
is at the start of the 4th line due to the previous execution of echo stdout1; echo stdout2; echo stdout3
.