Encountering IF statement and tee conflict in script

Joined
Aug 27, 2020
Messages
2
Reaction score
2
Credits
33
Hi All

I'm looking to be able to correctly evaluate my IF statement and also output what has been backed up into a log file.

In the function at the bottom I am stuck between getting the IF statement to evaluate correctly and managing to log what has been backed up (synchronised with rsync).

If I use the option at the bottom then my IF statement seems to work properly but the tee option freezes the script.

If I comment out the tee option then my IF statement works and the script completes correctly but I’m missing the logging of what has been backed up.

If I use the following then the logging works but the IF statement appears to apply to the tee command, potentially making the IF statement inaccurate (as the backup might fail but the tee command could complete successfully).

Bash:
 if sudo rsync -av --exclude '.*' --exclude 'VirtualBox\ VMs' $BACKUPSOURCE $BACKUPDESTINATION | tee -a /home/user/log/rsynctest.txt

Bash:
backupfunction () {
    BACKUPSOURCE=/home/user/
    BACKUPDESTINATION=/backup/location/user/        # Be aware a directory may be created if it does not exist.
          
       if sudo rsync -av --exclude '.*' --exclude 'VirtualBox\ VMs' $BACKUPSOURCE $BACKUPDESTINATION
           then
            tee -a /home/user/log/rsynctest.txt
            echo "Backed Up"
            # return to the script.
            return 0
            else
            echo "Not Backed Up"
            FUNCTIONSTATUS="Failed"
            echo -e "$SCRIPTNAME\t${FUNCNAME[0]}\t$(date +%x)\t$(date +%X)\t$FUNCTIONSTATUS\tScript terminated. Error encountered attempting to backup." | tee -a /home/user/Logs/ScriptLogTest.txt
            # terminate the script with errors.
            exit 1
        fi
}
 


I think I see the problem.

Try adding this line to your script.

#!/bin/bash
set -x
...rest of code here...
 
I don't do much bash scripting, but it looks to me like the problem is that you're saying "if rsync command works, then execute the tee command to log and then return to the script" By the time the 'tee' command executes, the rsync has finished and there's nothing to log. Try putting the tee command before the if statement.

keith
 
G'day, all :)

Moving this to Command Line, where scripting inquiries are more noticeable.

Welcome @usernamesaredifficult and Good Luck.

Avagudweegend

Chris Turner
wizardfromoz
 
@khedger is bang on the money.
Normally you'd pipe the output of a command to tee.
Your tee command is receiving no input whatsoever.

The best way to fix this problem would be to enclose the entire if..else.. conditional block inside a set of curly braces {}. Which has the effect of grouping all of the commands inside the braces together, as if they are a single operation. Then we can pipe ALL of the output from all those commands into tee, in order to append to the log-file.

Which will make your script/function look like this:
Bash:
backupfunction () {
    BACKUPSOURCE=/home/user/
    BACKUPDESTINATION=/backup/location/user/        # Be aware a directory may be created if it does not exist.
       
       { if sudo rsync -av --exclude '.*' --exclude 'VirtualBox\ VMs' $BACKUPSOURCE $BACKUPDESTINATION
           then
            echo "Backed Up"
            # return to the script.
            return 0
            else
            echo "Not Backed Up"
            FUNCTIONSTATUS="Failed"
            echo -e "$SCRIPTNAME\t${FUNCNAME[0]}\t$(date +%x)\t$(date +%X)\t$FUNCTIONSTATUS\tScript terminated. Error encountered attempting to backup." | tee -a /home/user/Logs/ScriptLogTest.txt
            # terminate the script with errors.
            exit 1
        fi } | tee -a /home/user/log/rsynctest.txt
}

So that's a neat little trick you can do with curly braces!
If you enclose a set of commands in curly braces, you can pipe, or redirect the outputs of all of them to a file, or to another program using a single redirect.
 
Thanks for the feedback everyone, it’s been very helpful. Apologies for posting it in the wrong area and thanks @wizardfromoz for relocating it.

@dos2unix, I did not know about the set -x, which I’m sure will be help in the future as well as now.

@khedger and @JasKinasis thanks for the explanations. I followed the example given by @JasKinasis but encountered the following problems:
  1. I am trying to create 2 separate log files. One log tracks what files have been backed up by rsync and one that logs what errors have been encountered in the backup process and in this method I couldn’t quite seem to get the separation I wanted.
  2. The exit 1 statement does not appear to function properly within the additional brackets. When the extra brackets are removed, the script terminates. When in the brackets the script (although it logs the error) it does not terminate the script but returns to the main script and carries on with the next function.
In the end I chose the slightly untidy and possibly bad practice method of simply repeating the command under the assumption that both commands will either fail or succeed and the first command is to perform the backup and log which files have been copied and the second command is to check whether the command worked and to either return to the main script or to terminate (exit) the script:

Bash:
sudo rsync -av --exclude '.*' --exclude 'VirtualBox\ VMs' $BACKUPSOURCE $BACKUPDESTINATION | tee -a /home/user/log/rsynctest.txt
 
 if sudo rsync -av --exclude '.*' --exclude 'VirtualBox\ VMs' $BACKUPSOURCE $BACKUPDESTINATION

Any further feedback on my chosen solution or the topic is welcome.
 
Hmmm......isn't there a way to redirect error output specifically in bash? I seem to remember &2 or something being a designation for error output and the use of something like '&2 > myerror.log' to get separate error output. @JasKinasis should know....

keith
 
Last edited by a moderator:

Members online


Latest posts

Top