bashshellshexectee

multiple call of exec > >(tee -a "${logFile}") 2>&1 with different log files


Look like if I call exec > >(tee -a "${logFile}") 2>&1 multiple times in the same script with different log files, the first log files will get appended multiple times. Is there a way to reset exec call before calling exec > >(tee -a "${logFile}") 2>&1 ?

$ cat sample.bash 
#!/bin/bash -e

function redirectOutputToLogFile()
{
    local -r logFile="${1}"

    mkdir -p "$(dirname "${logFile}")"
    exec > >(tee -a "${logFile}") 2>&1
}

function main()
{
    redirectOutputToLogFile 'test1.log'
    echo 'hello 1'

    redirectOutputToLogFile 'test2.log'
    echo 'hello 2'

    redirectOutputToLogFile 'test3.log'
    echo 'hello 3'
}

main "${@}"

$ ./sample.bash 
hello 1
hello 2
hello 3


$ cat test1.log 
hello 1
hello 2
hello 3

$ cat test2.log 
hello 2
hello 3

$ cat test3.log 
hello 3

Solution

  • You should back up the original descriptors (stdout and stderr) at the very beginning, and then restore them before the exec redirection.

    #!/bin/bash -e
    
    # backup stdout/stderr in file descriptor 3 and 4 resp.
    exec 3>&1 4>&2
    
    function redirectOutputToLogFile()
    {
        local -r logFile="${1}"
    
        mkdir -p "$(dirname "${logFile}")"
        exec 1>&3 2>&4  # restore orig state of stdout/stderr
        exec > >(tee -a "${logFile}") 2>&1
    }