From 6e0c807dc048c46c28ed9015ae0473094cd8c372 Mon Sep 17 00:00:00 2001 From: Matan Horovitz Date: Tue, 18 Jan 2022 22:14:13 +0200 Subject: [PATCH] This is much cooler now --- Kumonoboru | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100755 Kumonoboru diff --git a/Kumonoboru b/Kumonoboru new file mode 100755 index 0000000..92f3d0d --- /dev/null +++ b/Kumonoboru @@ -0,0 +1,178 @@ +#!/bin/bash +##Simple script to run Restic backups +source $SCRIPTS/Okiru +source /etc/environment +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: /Red-Vol/Media/Pictures)" + echo "Pukeko-XYZ-Containers Containers (path: /Red-Vol/Media/Containers)" + echo "Pukeko-XYZ-Cloud Data from all devices (path: /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 Restic +#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 -r b2:"$REPOSITORY" backup "$REPOSITORY_PATH" --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT"; 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" +## ^ 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"; then + ok "Repository $REPOSITORY passed integrity check!" + info "Current snapshots:" + restic -r b2:"$REPOSITORY" snapshots >> $LOG + if [[ -z $PRUNE ]] && [[ $(date +%d) == "18" ]]; then +#Only clean the repository if ^not done already ^ and today is the 18th of the month (prune monthly) + info "Monthly prune is today; cleaning $REPOSITORY" + clean "$REPOSITORY" + fi + 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"; 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 /Red-Vol/Media/Pictures/ + ;; + (Pukeko-XYZ-Containers) + backup Pukeko-XYZ-Containers /Red-Vol/Media/Containers + ;; + (Pukeko-XYZ-Cloud) + backup Pukeko-XYZ-Cloud /Red-Vol/Media/Cloud/Syncthing + ;; + (*) + help;; + esac +#If cleaning was not forced, backup the repositories +elif [[ -z $CLEAN ]]; then + backup Gerbil-TK /Red-Vol/Media/Pictures/ + backup Pukeko-XYZ-Containers /Red-Vol/Media/Containers + backup Pukeko-XYZ-Cloud /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 ]]; then + clean Gerbil-TK + clean Pukeko-XYZ-Containers + clean Pukeko-XYZ-Cloud +fi