Search code examples
bashio-redirection

bash redirect to the same file in a bad manner


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.


Solution

  • 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.