1

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?

Master DJon
  • 1,899
  • 2
  • 19
  • 30

1 Answers1

1

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

Master DJon
  • 1,899
  • 2
  • 19
  • 30
  • 1
    Good for sticking with it and making the executive decision. Another option that comes to mind is a "State File" that holds the name of the file underlying tee. You can set `trap` to remove the file when the script finally exits (may need a wrapper around the script that relaunches things). That would also provide a simple test to determine if the current process was a relaunch. – David C. Rankin Jan 30 '22 at 05:08
  • @DavidC.Rankin Could have been that too having an `if` checking for the file descriptor #3 to set trap. So on launch "file creation" and on relaunch "`trap`". If you are interested to look at the real script using this (my backup script): https://github.com/djon2003/com.cyberinternauts.linux.backup – Master DJon Jan 30 '22 at 15:53