linuxshqnap

Retrieve underlying file of tee command


References

Fullcode of what will be discussed here: https://github.com/djon2003/com.cyberinternauts.linux.backup

activateLogs question that solved how to log to file and screen: https://stackoverflow.com/a/70792273/214898

Limitation

Just a small reminder from the last question: this script is executed on limited environment, on a QNAP (NAS).

Background

I have a function that activate logging which now has three modes: SCREEN, DISK, BOTH. With some help (from the question of the link above), I achieve to make work the BOTH option. DISK & BOTH use a file descriptor numbered 3. The first is pointing to a file and the second to stdout.

On exit of my script (using trap), it detects if there were logged errors and send them via email.

Code

function sendErrorMailOnExit()
{
    ## If errors happened, then send email
    local isFileDescriptor3Exist=$(command 2>/dev/null >&3 && echo "Y")
    if [ "$isFileDescriptor3Exist" = "Y" ]; then
        local logFile=$(readlink /proc/self/fd/3 | sed s/.log$/.err/)
        local logFileSize=$(stat -c %s "$logFile")
        if [ $logFileSize -gt 0 ]; then
            addLog "N" "Sending error email"
            local logFileName=$(basename "$logFile")
            local logFileContent=$(cat "$logFile")
            sendMail "Y" "QNAP - Backup error" "Error happened on backup. See log file $logFileName\n\nLog error file content:\n$logFileContent"
        fi
    fi
}
trap sendErrorMailOnExit EXIT

Problem

As you can see, this works well because the file descriptor #3 is using a file. But now, using the BOTH option, the file descriptor #3 is pointing to stdout and the file is written via tee. Hence my question, how could I get the location of the file of tee.

Why not only using a variable coming from my function activateLogs would you say? Because, this function relaunches the script to be able to get all the logs not caught before the function is called. Thus why using this method to retrieve the error file location.

Possible solutions, but not the best (I hope)

  1. One way would be to pass the file location through a script parameter, but I would prefer not do that if that can be avoid.
  2. Another, would be to create a "fake" file descriptor #4 (probably my best solution up to now) that would always point to the file.

Does anyone have an idea?


Solution

  • I finally opted for the creation of a "fake" file descriptor #4 that does not nothing except pointing to the current log file.