3 Commits
1.1 ... 1.2.1

Author SHA1 Message Date
a708ec80ca Add user option
Added a command line option to specify the user performing the backup.
This is useful if running the program with sudo.
2015-11-26 01:03:33 +01:00
f5365fddff Add warning in example configuration 2015-11-25 13:26:57 +01:00
473ee59868 Improve configuration file parsing
The configuration file is now parsed with a simple awk program
which is simpler to understand and maintain
2015-11-25 12:33:49 +01:00
2 changed files with 79 additions and 151 deletions

2
config
View File

@ -1,5 +1,7 @@
#Example config file for my_backup #Example config file for my_backup
# WARNING: Values should NOT be quoted, e.g. use inputs=/some/dir instead of inputs="/some/dir"
#Input directories. Use a comma to separate items #Input directories. Use a comma to separate items
inputs=/home/my_home,/etc inputs=/home/my_home,/etc

View File

@ -15,7 +15,7 @@
#You should have received a copy of the GNU General Public License #You should have received a copy of the GNU General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>. #along with this program. If not, see <http://www.gnu.org/licenses/>.
#Version 1.1 #Version 1.2.1
#Simple backup script. Reads options, sources and destination from a configuration file or standard input #Simple backup script. Reads options, sources and destination from a configuration file or standard input
#Help function #Help function
@ -35,6 +35,8 @@ function help_function {
echo " the backup." echo " the backup."
echo "-k, --keep NUMBER Specify the number of old backups to keep." echo "-k, --keep NUMBER Specify the number of old backups to keep."
echo " Default: keep all." echo " Default: keep all."
echo "-u, --user USER User performing the backup."
echo " Default: current user."
echo "" echo ""
echo "If no option is given, the program uses the default" echo "If no option is given, the program uses the default"
echo "configuration file: $HOME/.simple_backup/config." echo "configuration file: $HOME/.simple_backup/config."
@ -74,83 +76,28 @@ function read_conf {
fi fi
while read line #Create temporary files
do
#Ignore comments and empty lines
if [[ $line == \#* || $line == "" ]]; then
continue
else
#Get option name and values for the current line
var=$(echo "$line" | cut -d"=" -f1)
case "$var" in
#Files/folders to backup
inputs)
#Create a temporary file to store inputs
INPUTS=$(mktemp) INPUTS=$(mktemp)
tmp=$(echo "$line" | cut -d"=" -f2) EXCLUDE=$(mktemp)
n=$(echo "$tmp" | awk -F ',' '{print NF}') #Files/folders must be separated with commas BACKUP=$(mktemp)
i=1 NKEEP=$(mktemp)
#j=1
n_in=0
#Read each input and save it to the INPUTS file #Parse the configuration file
while [[ $i -le $n ]] awk -v INPUTS="$INPUTS" -v EXCLUDE="$EXCLUDE" -v BACKUP="$BACKUP" \
do -v NKEEP="$NKEEP" -v UHOME="$HOME/" -F '[=,]' \
input=$(echo "$tmp" | cut -d"," -f$i) '$1=="inputs" { for ( i=2; i<=NF; i++ ) { sub(/^~\//,UHOME,$i); print $i > INPUTS } }
input=$(echo "$input" | tr -d \"\') $1=="backup_dir" { sub(/^~\//,UHOME,$2); print $2 > BACKUP }
$1=="exclude" { for ( i=2; i<=NF; i++ ) { sub(/^~\//,UHOME,$i); print $i > EXCLUDE } }
$1=="keep" { if ( $2 != NULL ) { print $2 > NKEEP } }' $CONFIG
if [[ "$input" =~ ^~/ ]]; then BACKUP_DEV=$(cat $BACKUP)
input=$(echo ${input/\~/$HOME}) KEEP=$(cat $NKEEP)
fi
if [[ ! -e "$input" ]]; then rm "$BACKUP"
#Warn the user if an input doesn't exist rm "$NKEEP"
echo "Warning: input \"$input\" not found. Skipping" | tee -a $HOME/.simple_backup/warning.log
else
n_in=$((n_in+1))
fi
echo "$input" >> $INPUTS if [[ -z "$BACKUP_DEV" || ! -d "$BACKUP_DEV" ]]; then
#If the backup directory is not set or doesn't exist, exit
i=$((i+1))
done
;;
#Directory where the backup is saved
backup_dir)
BACKUP_DEV=$(echo "$line" | cut -d"=" -f2)
BACKUP_DEV=$(echo "$BACKUP_DEV" | tr -d \"\')
if [[ "$BACKUP_DEV" =~ ^~/ ]]; then
BACKUP_DEV=$(echo ${BACKUP_DEV/\~/$HOME})
fi
if [[ -z "$BACKUP_DEV" ]]; then
#If the backup directory is not set, exit
echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log
echo "Error: No backup folder set in configuration file" | tee -a $HOME/.simple_backup/errors.log
#If libnotify is installed, show desktop notification that backup failed
! command -v notify-send > /dev/null 2>&1 || DISPLAY=:0.0 notify-send -u low -t 10000 "Backup failed"
if [[ -f $HOME/.simple_backup/simple_backup.log.old ]]; then
rm -f $HOME/.simple_backup/simple_backup.log.old
fi
if [[ -f $HOME/.simple_backup/errors.log.old ]]; then
rm -f $HOME/.simple_backup/errors.log.old
fi
if [[ -f $HOME/.simple_backup/warnings.log.old ]]; then
rm -f $HOME/.simple_backup/warnings.log.old
fi
exit 1
fi
if [[ ! -d "$BACKUP_DEV" ]]; then
#If the backup directory doesn't exist, exit
echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log
echo "Error: Output folder \"$BACKUP_DEV\" not found" | tee -a $HOME/.simple_backup/errors.log echo "Error: Output folder \"$BACKUP_DEV\" not found" | tee -a $HOME/.simple_backup/errors.log
#If libnotify is installed, show desktop notification that backup failed #If libnotify is installed, show desktop notification that backup failed
@ -168,6 +115,9 @@ function read_conf {
rm -f $HOME/.simple_backup/warnings.log.old rm -f $HOME/.simple_backup/warnings.log.old
fi fi
rm "$INPUTS"
rm "$EXCLUDE"
exit 1 exit 1
fi fi
@ -185,44 +135,8 @@ function read_conf {
#Set the backup directory variable to the newly created subfolder #Set the backup directory variable to the newly created subfolder
BACKUP_DIR="$BACKUP_DIR/$DATE" BACKUP_DIR="$BACKUP_DIR/$DATE"
;;
#Files/directories/patterns to exclude from backup n_in=$(cat $INPUTS | wc -l)
exclude)
#Create temp file to store exclude patterns
EXCLUDE=$(mktemp)
temp=$(echo "$line" | cut -d"=" -f2)
i=1
n=$(echo "$temp" | awk -F ',' '{print NF}') #Exclude patterns must be separated by commas
#Read each exclude pattern and save it in the temp file
while [[ $i -le $n ]]
do
var=$(echo "$temp" | cut -d"," -f$i)
var=$(echo "$var" | tr -d \"\')
if [[ "$var" =~ ^~/ ]]; then
var=$(echo ${var/\~/$HOME})
fi
echo "$var" >> $EXCLUDE
i=$((i+1))
done
;;
#Number of old backups to keep
keep)
KEEP=$(echo "$line" | cut -d"=" -f2)
;;
#Unrecognized options
*)
#Skip unrecognised options
echo "$(date): Warning: option \"$var\" not recognised. Skipping" >> $HOME/.simple_backup/warnings.log
;;
esac
fi
done<"$CONFIG"
return return
} }
@ -231,6 +145,9 @@ function read_conf {
function parse_options { function parse_options {
i=1 i=1
n_in=0 n_in=0
#Create a temporary file to store inputs
INPUTS=$(mktemp)
#Create temp file to store exclude patterns #Create temp file to store exclude patterns
EXCLUDE=$(mktemp) EXCLUDE=$(mktemp)
@ -254,12 +171,13 @@ function parse_options {
mv -f $HOME/.simple_backup/warnings.log.old $HOME/.simple_backup/warnings.log mv -f $HOME/.simple_backup/warnings.log.old $HOME/.simple_backup/warnings.log
fi fi
rm $INPUTS
rm $EXCLUDE
exit 0 exit 0
;; ;;
-i | --input) -i | --input)
#Create a temporary file to store inputs
INPUTS=$(mktemp)
while [[ "$#" -gt 1 && ! "$2" =~ ^- ]] while [[ "$#" -gt 1 && ! "$2" =~ ^- ]]
do do
@ -354,13 +272,21 @@ function parse_options {
;; ;;
-c | --config) -c | --config)
if [[ -f "$EXCLUDE" ]]; then
rm "$EXCLUDE" rm "$EXCLUDE"
fi rm "$INPUTS"
read_conf "$2" read_conf "$2"
return return
;; ;;
-u | --user)
rm "$EXCLUDE"
rm "$INPUTS"
config="/home/$2/.simple_backup/config"
read_conf "$config"
return
;;
*) *)
echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log
echo "Error: Option $1 not recognised. Use 'simple-backup -h' to see available options" | tee -a $HOME/.simple_backup/errors.log echo "Error: Option $1 not recognised. Use 'simple-backup -h' to see available options" | tee -a $HOME/.simple_backup/errors.log
@ -496,9 +422,9 @@ if [[ ! -z "$INPUTS" ]]; then
fi fi
if [[ -z "$LAST_BACKUP" ]]; then if [[ -z "$LAST_BACKUP" ]]; then
rsync -acrv -H -X -R --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log" rsync -acrv -H -X -R --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" --ignore-missing-args >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log"
else else
rsync -acrv -H -X -R --link-dest="$LAST_BACKUP" --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log" rsync -acrv -H -X -R --link-dest="$LAST_BACKUP" --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" --ignore-missing-args >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log"
fi fi
#Update the logs #Update the logs