#!/bin/bash # Accept the following # 1 - source directory # Default to $HOME # 2 - destination directory # Mandatory # Exclude destination directory from backup # 2 - Backup_name # Default to $USER # 3 - Unique Identifier # Default to $HOST # 4 - Log Directory # Default to /var/log/borg # Create if does not exist # BORG_PASSPHRASE # Default to blank # Display usage on -h and on wrong params ############################################################## # Usage ############################################################## function usage() { if [ -n "$1" ]; then echo "" echo -e "${CRED}$1${CEND}\n" fi echo "Usage: bash $0 -dstdir path [-srcdir path] [-name name] [-uname uname] [-logdir path] [-pass passphrase]" echo " -dstdir Directory where borg will create backup files" echo " Will be created if it does not exist" echo " -srcdir Directory that you want to backup (Default is \$HOME)" echo " -name Name for the backup. Useful when you use borg to create multiple backups on a system" echo " -uname Unique name to identify backup from this system from other systems" echo " Default is \$HOST" echo " -logdir Directory where log files will be created. Default /var/log/borg" echo " Will be created if it does not exist" echo " -pass borg will encrypt the backup with this passphrase" echo " -h|--help Displays this help text" echo "" echo "Example: bash ./$0 -dstdir ${HOME}/backups -name home -logdir ${HOME}/backups/logs" printf "\\nBelow restrictions apply to passphrase - \\n" printf "%2s - [a-zA-Z0-9] [-] [_] are allowed\\n%2s - NO special characters.\\n%2s - NO spaces.\\n" " " " " " " if [ -n "$1" ]; then exit 2 fi } ############################################################## # Parse and validate arguments ############################################################## while [[ "${#}" -gt 0 ]]; do case $1 in -dstdir) # If it exists > Check if you have write access if [[ (-d "$2") && (-r "$2") && (-w "$2") && (-x "$2")]]; then backup_dir="$2" else echo echo "Can't access the backup directory ${2}" echo "You need to have write access to backup destination directory." exit 5 fi # Create if it does not exist if [[ ! -d "$2" ]]; then mkdir -p "$2" return_code=$? if [[ $return_code != 0 ]]; then echo "Error creating backup directory ${2}" exit 6 fi fi backup_dir="$2" echo "$backup_dir" shift 2 ;; -srcdir) # Check if it exists if [[ -d "$2" ]]; then source_dir="$2" else echo "No directory to backup. ${2} not found." exit 7 fi shift 2 ;; -name) backup_name="$2" shift 2 ;; -uname) unique_identifier="$2" shift 2 ;; -logdir) # If it exists > Check if you have write access if [[ (-d "$2") && (-r "$2") && (-w "$2") && (-x "$2")]]; then log_dir="$2" else echo "Can't access the log directory ${2}" exit 8 fi # Create if it does not exist if [[ ! -d "$2" ]]; then mkdir -p "$2" return_code=$? if [[ $return_code != 0 ]]; then echo "Error creating log directory ${2}" exit 9 fi fi log_dir="$2" shift 2 ;; -pass) BORG_PASSPHRASE="$2" shift 2 ;; -h|--help) echo usage echo exit 0 ;; *) usage "Unknown parameter passed: $1" "h" exit 3 ;; esac done # TODO - Display usage() error when dstdir is NOT provided by user ############################################################## # Default values ############################################################## # If nothing provided by user assign defaults backup_name=$USER unique_identifier="$HOST" log_dir=/var/logs/borg/ source_dir="$HOME" exit ######################################################################### # Setting this, so you won't be asked for your repository passphrase: export BORG_PASSPHRASE # Setting this, so the repo does not need to be given on the commandline: export BORG_REPO=$backup_dir$backup_name # some helpers and error handling: log_file=$log_dir$backup_name-$(date +%d%m%Y-%H%M%S) readonly log_file # if borg is currently running - stop sync if [[ "$(pidof borg -s | wc -w)" -eq 1 ]] then echo "Another Backup is currently running. Exiting." >> "$log_file" 2>&1 exit 1 fi info() { printf "\n%s %s\n\n" "$( date )" "$*" >> "$log_file" 2>&1; } trap 'echo $( date ) Backup interrupted >> "$log_file" 2>&1; exit 255' INT TERM info "Starting backup" >> "$log_file" 2>&1 # Backup the most important directories into an archive named after # the machine this script is currently running on: borg create \ --verbose \ --filter AME \ --list \ --stats \ --show-rc \ --compression zstd,1 \ --exclude-caches \ --exclude '/home/*/.cache/*' \ --exclude '/home/*/.local/share/Trash/*' \ --exclude '/home/*/Downloads/Videos/*' \ --exclude '/home/*/Downloads/Study/Video/*' \ --exclude "$backup_dir" \ --exclude "$log_file" \ \ ::"$unique_identifier-$backup_name-{now}" \ "$source_dir" \ >> "$log_file" 2>&1 backup_exit=$? if [[ $backup_exit == 0 ]] then info "Back up completed successfully" else info "Back up error - Check ${log_file} for details" fi # PRUNE info "Pruning repository" >> "$log_file" 2>&1 # Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly # archives of THIS machine. The '{hostname}-' prefix is very important to # limit prune's operation to this machine's archives and not apply to # other machines' archives also: borg prune \ --list \ --stats \ --prefix "$unique_identifier-$backup_name" \ --show-rc \ --keep-within 2d \ --keep-last 10 \ --keep-daily 7 \ >> "$log_file" 2>&1 prune_exit=$? if [[ $prune_exit == 0 ]] then info "Pruning completed successfully" else info "Pruning error - Check ${log_file} for details" fi # use highest exit code as global exit code global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) echo Status Code - $global_exit >> "$log_file" 2>&1 exit ${global_exit}