#!/bin/bash ##Simple script to run Restic backups source /root/.bash_profile source /home/shmick/Scripts/Okiru source /etc/environment export HOME=/root/ arg0=$(basename "$0") #Show help if arguments are misused usage() { exec 1>2 # Send standard output to standard error help exit 1 } flag_error() { echo -e "$arg0: $*." >&2 help exit 1 } help() { echo "$arg0 - Back up important location to the B2 cloud using Restic." echo " {-c|--clean} -- Force prune of the remote repositories" echo " {-r|--repository} repository -- Only backup the specified repository." echo " {-l|--limit} #[Kbps] -- Limit upload & download speed" echo " {-h|--help} -- Print this help message and exit" echo "Available repositories:" echo "Gerbil-TK Photos (path: /var/Red-Vol/Media/Pictures)" echo "Pukeko-XYZ-Containers Containers (path: /var/Red-Vol/Media/Containers)" echo "Pukeko-XYZ-Cloud Data from all devices (path: /var/Red-Vol/Media/Cloud/Syncthing)" exit 0 } #Pass arguments to the script flags() { #This is utterly useless if [[ $# == "0" ]]; then : fi while test $# -gt 0 do case "$1" in (-c|--clean) debug "Cleaning will take place per request." export CLEAN="1" shift;; (-r|--repository) shift export REPOSITORY="$1" debug "Only repository $1 will be processed per request." shift;; (-l|--limit) shift export BWLIMIT="$1" debug "Bandwidth will be limited to $BWLIMIT Kbps per request." shift;; (-h|--help) help;; (*) help;; esac done } flags "$@" logging Kumonoboru #Defaults if [[ -z $BWLIMIT ]]; then export BWLIMIT="0" fi #Safety function; accepts repository to check safety(){ REPOSITORY="$1" info "Checking if repository $REPOSITORY is in use..." #Check no other Restic process is using this repository; Free unnecessary locks, if present if [[ -n $(ps aux | grep restic | grep "$REPOSITORY") ]]; then warn "Repository $REPOSITORY is in use - ignoring" return 1 # ^ If there's a restic process holding the repository, leave it alone. else info "Repository $REPOSITORY is not in use - unlocking" restic -r b2:$REPOSITORY unlock # ^ If a lock exists but no process, the repository is safe and should be unlocked. fi } #Backup function; accepts repository and path to backup backup(){ REPOSITORY="$1" REPOSITORY_PATH="$2" if safety "$REPOSITORY"; then #Run the backup info "Backing up repository $REPOSITORY" if restic --cache-dir="$RESTIC_CACHE_DIR" -r b2:"$REPOSITORY" backup "$REPOSITORY_PATH" --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT" | tee -a $LOG; then ok "Path $REPOSITORY_PATH completed upload to $REPOSITORY." check "$REPOSITORY" else error "Repository $REPOSTIORY failed to upload path $REPOSITORY_PATH!" fi fi } check(){ REPOSITORY="$1" PRUNE="$2" debug "Working on Repostory $1 with prune option $2" ## ^ This variable will have value if repo is already clean, indicating #+ This is a post backup check. if [[ -n $PRUNE ]]; then warn "This repository has been cleaned already; will not clean again." fi if safety "$REPOSITORY"; then info "Checking repository $REPOSITORY" if restic -r b2:"$REPOSITORY" check --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT" | tee -a $LOG; then ok "Repository $REPOSITORY passed integrity check!" info "Current snapshots:" restic -r b2:"$REPOSITORY" snapshots | tee -a $LOG else error "Repository $REPOSITORY failed integrity check!" fi fi } clean(){ REPOSITORY="$1" if safety "$REPOSITORY"; then info "Cleaning repository $REPOSITORY" if restic -r b2:$REPOSITORY forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT" | tee -a $LOG; then ok "Repository $REPOSITORY is trim!" debug "Running post clean check..." check "$REPOSITORY" "1" # Marks repository as cleaned already ^ so it won't passed to this function again. else error "Repository $REPOSITORY failed to prune!" fi fi } #If a specific repository was requested, back it up; otherwise, back them all up. if [[ -n $REPOSITORY ]] && [[ -z $CLEAN ]]; then case "$REPOSITORY" in (Gerbil-TK) backup Gerbil-TK /var/Red-Vol/Media/Pictures/ ;; (Pukeko-XYZ-Containers) backup Pukeko-XYZ-Containers /var/Red-Vol/Media/Containers ;; (Pukeko-XYZ-Cloud) backup Pukeko-XYZ-Cloud /var/Red-Vol/Media/Cloud/Syncthing ;; (*) help;; esac #If cleaning was not forced, backup the repositories elif [[ -z $CLEAN ]]; then backup Gerbil-TK /var/Red-Vol/Media/Pictures/ backup Pukeko-XYZ-Containers /var/Red-Vol/Media/Containers backup Pukeko-XYZ-Cloud /var/Red-Vol/Media/Cloud/Syncthing #If a specific repository was requested to be cleaned, clean it elif [[ -n $REPOSITORY ]] && [[ -n $CLEAN ]]; then case "$REPOSITORY" in (Gerbil-TK) clean Gerbil-TK ;; (Pukeko-XYZ-Containers) clean Pukeko-XYZ-Containers ;; (Pukeko-XYZ-Cloud) clean Pukeko-XYZ-Cloud ;; (*) help;; esac #If cleaning was forced and no repository specified, clean all repositories elif [[ -n $CLEAN ]] || [[ $(date +%a) == "Friday" ]]; then clean Gerbil-TK clean Pukeko-XYZ-Containers clean Pukeko-XYZ-Cloud fi #Wrap up this run's log and report nicely echo "All done; have a nice day!" end_logging exit 0