backup-rclone/backup-rclone.sh

145 lines
5.2 KiB
Bash
Raw Normal View History

2023-09-02 19:49:37 +02:00
#!/bin/bash
MAX_NAME_WIDTH=50 # Maximal length of name next to the progress bar in percent (%)
tempdir=$(mktemp -d /tmp/backup-XXXXXXXXXX)
existing=()
recursive_backup() {
hashtemp=$(mktemp $tempdir/hashes-XXXXXXXXXXXXXXX.db) # /tmp dir for saving data and encrypting files
if [[ -n $(rclone lsf "backup:$hashdb" 2>/dev/null) ]]; then # if hash file exists, copy it to tmp dir
rclone cat "backup:$hashdb" > $hashtemp
fi
trap "cleanup $hashtemp $hashdb" SIGINT
trap "cleanup $hashtemp $hashdb" SIGTSTP
for dir in "${include[@]}"; do # go through all included directories
done_files=0
progress=0
total_files=$(wc -l <<<$(find "$dir" -type f)) # count all files for progress bar
action=""
for i in "${exclude[@]}"; do if [[ "$dir" == "$i" ]]; then continue; fi; done # if dir in exclude, skip it # TODO: POSSIBLE WHOOPSIE!
while read k; do # take every file and make a backup
if [[ ${k///} == $k ]]; then filepath="."; else filepath=${k%/*}; fi # if file in root of dir, change the path to not crash everything ,else get filepath
draw_progress $(($progress)) "$k" "$action"
#remotehash="$(cat $hashtemp | grep -n "$k")" # old databese
sqlcommand="SELECT hash FROM files WHERE backpath=\"${k}\""
remotehash="""$(sqlite3 $hashtemp "$sqlcommand")""" # get hash from database
if [[ -z $remotehash ]]; then entryexists=false; else entryexists=true; fi # if file entry (and hash) exists, save as bool
localhash="$(md5sum "$k")" # hash of local version of file
done_files=$(($done_files+1))
progress=$(($done_files*100/$total_files))
if [[ "$remotehash" == "$localhash" ]]; then action="Skip"; continue; fi # if the has his the same, skip backuup
action="Backup"
draw_progress $(($progress)) "$k" "$action"
if [[ $enctype == "gpg" ]]; then
gpg -e -r "$RECIPIENT_ID" -o "$tempdir/${k##*/}.gpg" "$k"
backupfile="$tempdir/${k##*/}.gpg"
else
backupfile="$k"
fi
if [[ $filepath == "." ]]; then flpth=""; else flpth="/$filepath"; fi
backup "$backupfile" "backup:$backdir$flpth"
done <<< "$(find "$dir" -type f)"
done
touch missing-files.txt
while read i; do # TODO: DELETE THIS PART
sfile="${i#* }"
if [[ -f "$sfile" ]]; then df="Hi"; else echo "Missing: $sfile"; echo "$sfile" >> missing-files.txt; fi
done <<<$(cat $hashtemp)
cleanup $hashtemp $hashdb
}
backup() { # backup 1:<file> 2:<remotedir>
if [[ *"${existing[@]}"* == "$2" ]]; then # if remote directory is set as existing, don't check it's existence
df="Hi"
else
if [[ -n $(rclone lsd "$2" 1>/dev/null) ]]; then # check if directory doesn't exist on server
rclone mkdir "$2"
fi
existing=("${existing[@]}" "$2")
fi
bool=0
rclone copy "$1" "$2" && bool=1
#if [[ $remoteline == "0" && $bool == 1 ]]; then echo "$localhash" >> $hashtemp; else sed -i "${remoteline}s|.*|${localhash}|" $hashtemp; fi # TODO: SQL ######
if [[ $bool==1 && $entryexists ]]; then
sqlcommand="UPDATE files SET hash=\"${localhash}\" WHERE backpath=\"${2}\"" #set new hash in database
sqlite3 $hashtemp "$sqlcommand"
else
if [[ "$enctype" == "gpg" ]]; then encdata="$RECIPIENT_ID"
else encdata=""; fi
sqlcommand="INSERT INTO files(backpath,localroot,hash,backupenc,encdata) VALUES(\'${2}\',\'$(pwd)\',\'$localhash\',\'${enctype}\',\'${encdata}\')"
sqlite3 $hashtemp "$sqlcommand"
fi
}
cleanup() { # 1:hashtemp 2:hashdb
echo -e "\ncleaning up..."
cd ${1%/*}
localhfile=${2##*/}
mv "${1##*/}" "$localhfile"
rclone move "$localhfile" backup:${2%/*}
finish
}
finish() {
rmdir $tempdir || rm -rf $tempdir
exit
}
draw_progress() { # draw_progress 1:<done_progress> 2:<filename> 3:<Action>
window_length=$(tput cols); window_length=$(($window_length-3)) # get max window length
max_name_length=$(($window_length*$MAX_NAME_WIDTH/100)) # calc max length of filepath
if [[ ${#2} -gt $max_name_length ]]; then # if filepath too long, cut it, else add whitespace
name="$(cut -c -$max_name_length <<< "$2")"
else
name="$2"
if [[ ${#name} -lt $max_name_length ]]; then
for _ in $(seq ${#name} $max_name_length); do name+=" "; done
fi
fi
window_length=$(($window_length-${#name})) # get length of progress bar
prog=$(($1*$window_length/100))
tot=$((window_length-1))
#echo -e "prog $prog tot $tot done $1 total $2 win $window_length"; return
# Delete the last two lines
printf "\033[3K"
# Restore the cursor position
printf "\033[u"
echo "Progress: $progress% Action: $3 "
printf "["
for _ in $(seq 1 $prog); do
printf "#"
done
for _ in $(seq $prog $tot); do
printf "-"
done
printf "]$name\n"
}
if [[ $# -eq 0 ]]; then
echo "Please select a directory for backup!"
exit
fi
cd $1
curdir=$(pwd)
# save cursor position
printf "\033[s"
# print two dummy lines
printf "\n\n"
if [[ $# -eq 1 ]]; then
if [[ -f ".backup.env" ]]; then
source .backup.env
if [[ -z ${backdir+x} || -z ${hashdb+x} ]]; then echo "ERROR: env-file doesn't hold needed variables!"; exit; fi
if [[ -n ${include+x} ]]; then include+=(".backup.env"); else include=(*); fi
if [[ -z ${exclude+x} ]]; then exclude=("uc3rumcr3urc34u09q347c7055030785c3cc30mq3rcmu83qm3m.notanonionlink"); fi
if [[ -z ${enctype+x} ]]; then enctype="plain"; fi
else echo "ERROR: env-file doesn't exist!!"; exit; fi
else
echo "too many args!"
exit
fi
rmdir $tempdir ||rm -rf $tempdir