From c1bd65a0a37cbed71e3dddfb8d3244c54e3a802c Mon Sep 17 00:00:00 2001 From: TheMightyV Date: Tue, 4 Jan 2022 20:00:50 +0100 Subject: local-ized and lower-cased local variables, descending sorting of snapshots, minor readability changes --- backends/borg.sh | 44 ++++++++++---------- backends/bup.sh | 54 ++++++++++++------------ backends/tar.sh | 70 ++++++++++++++++--------------- server.sh | 122 ++++++++++++++++++++++++++++++++++++------------------- 4 files changed, 169 insertions(+), 121 deletions(-) diff --git a/backends/borg.sh b/backends/borg.sh index f5930c8..0b28619 100644 --- a/backends/borg.sh +++ b/backends/borg.sh @@ -1,33 +1,33 @@ function borg_init() { export BORG_PASSCOMMAND="$BACKUP_PASSCOMMAND" - for BACKUP_DIR in ${BACKUP_DIRS[*]} + for backup_dir in ${BACKUP_DIRS[*]} do # borg will check if repo exists - borg init --encryption=repokey-blake2 "$BACKUP_DIR" + borg init --encryption=repokey-blake2 "$backup_dir" done } function borg_create_backup() { export BORG_PASSCOMMAND="$BACKUP_PASSCOMMAND" - RETCODE=255 - for BACKUP_DIR in ${BACKUP_DIRS[*]} + local retcode=255 + for backup_dir in ${BACKUP_DIRS[*]} do - export BORG_REPO="$BACKUP_DIR" + export BORG_REPO="$backup_dir" trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM - echo "borg: starting backup to \"$BACKUP_DIR\"" + echo "borg: starting backup to \"$backup_dir\"" borg create \ - "${BACKUP_DIR}::${BACKUP_NAME}_$(date +'%F_%H-%M-%S')" \ + "${backup_dir}::${BACKUP_NAME}_$(date +'%F_%H-%M-%S')" \ "$WORLD_NAME" \ --filter AME \ --compression lz4 \ --exclude-caches \ - backup_exit=$? + local backup_exit=$? - echo "borg: pruning repository at \"$BACKUP_DIR\"" + echo "borg: pruning repository at \"$backup_dir\"" borg prune \ --prefix '{hostname}-' \ @@ -36,13 +36,13 @@ function borg_create_backup() { --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 6 \ - "$BACKUP_DIR" + "$backup_dir" - prune_exit=$? + local prune_exit=$? # use highest exit code as global exit code - global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) - RETCODE=$(( global_exit > RETCODE ? global_exit : RETCODE )) + local global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) + retcode=$(( global_exit > retcode ? global_exit : retcode )) if [ ${global_exit} -eq 0 ]; then echo "borg: backup and prune finished successfully" @@ -53,29 +53,29 @@ function borg_create_backup() { fi #exit ${global_exit} done - return $RETCODE + return $retcode } # server_restore relies on output format of this function function borg_ls_dir() { export BORG_PASSCOMMAND="$BACKUP_PASSCOMMAND" - borg list "$1" | cut -d' ' -f1 + borg list "$1" | cut -d' ' -f1 | sort -r } function borg_ls_all() { export BORG_PASSCOMMAND="$BACKUP_PASSCOMMAND" - for BACKUP_DIR in ${BACKUP_DIRS[*]} + for backup_dir in ${BACKUP_DIRS[*]} do - echo "borg: backups in \"$BACKUP_DIR\":" - borg list "$BACKUP_DIR" | cut -d' ' -f1 + echo "borg: backups in \"$backup_dir\":" + borg list "$backup_dir" | cut -d' ' -f1 done } function borg_restore() { export BORG_PASSCOMMAND="$BACKUP_PASSCOMMAND" - REMOTE="$1" - SNAPSHOT="$2" + local remote="$1" + local snapshot="$2" - export BORG_REPO="$REMOTE" - borg extract "${REMOTE}::${SNAPSHOT}" + export BORG_REPO="$remote" + borg extract "${remote}::${snapshot}" } diff --git a/backends/bup.sh b/backends/bup.sh index a5ddb14..b57bd86 100644 --- a/backends/bup.sh +++ b/backends/bup.sh @@ -1,19 +1,19 @@ # use first not-remote backup directory as bup's local repository # defaults to ".bup" function bup_local() { - for BACKUP_DIR in ${BACKUP_DIRS[*]} + for backup_dir in ${BACKUP_DIRS[*]} do - if [[ $BACKUP_DIR != *:* ]]; then - echo "$BACKUP_DIR" + if [[ $backup_dir != *:* ]]; then + echo "$backup_dir" return fi done - echo ".bup" + echo ".bup" } function bup_init() { bup -d "$(bup_local)" index "$WORLD_NAME" - status=$? + local status=$? if [ $status -ne 0 ]; then echo "bup: no local repo found, creating..." bup -d "$(bup_local)" init -r "$(bup_local)" @@ -27,49 +27,51 @@ function bup_create_backup() { bup -d "$(bup_local)" index "$WORLD_NAME" # 0 if saved to at least one non-local repository - RETCODE=1 - for BACKUP_DIR in ${BACKUP_DIRS[*]} + # TODO make more strict? + local retcode=1 + for backup_dir in ${BACKUP_DIRS[*]} do - echo "bup: backing up to \"$BACKUP_DIR\"" + echo "bup: backing up to \"$backup_dir\"" # try to save to remote - bup -d "$(bup_local)" save -r "$BACKUP_DIR" -n "$BACKUP_NAME" "$WORLD_NAME" + bup -d "$(bup_local)" save -r "$backup_dir" -n "$BACKUP_NAME" "$WORLD_NAME" + local status=$? # if failed - reinit remote and try again - if [ ! $? -eq 0 ]; then - echo "bup: failed backing up to \"$BACKUP_DIR\", reinitializing remote..." - bup -d "$(bup_local)" init -r "$BACKUP_DIR" - if [ ! $? -eq 0 ]; then - echo "bup: created remote at \"$BACKUP_DIR\"" - bup -d "$(bup_local)" save -r "$BACKUP_DIR" -n "$BACKUP_NAME" "$WORLD_NAME" + if [ $status -ne 0 ]; then + echo "bup: failed backing up to \"$backup_dir\", reinitializing remote..." + bup -d "$(bup_local)" init -r "$backup_dir" + if [ $? -ne 0 ]; then + echo "bup: created remote at \"$backup_dir\"" + bup -d "$(bup_local)" save -r "$backup_dir" -n "$BACKUP_NAME" "$WORLD_NAME" else - echo "bup: failed to make remote at \"$BACKUP_DIR\", moving on" + echo "bup: failed to make remote at \"$backup_dir\", moving on" fi else - if [ "$BACKUP_DIR" = "$(bup_local)" ]; then - RETCODE=0 + if [ ! "$backup_dir" = "$(bup_local)" ]; then + retcode=0 fi fi done echo "bup: backup finished" - return $RETCODE + return $retcode } # server_restore relies on output format of this function function bup_ls_dir() { - bup -d "$(bup_local)" ls -r "$BACKUP_DIR" "$BACKUP_NAME" + local backup_dir="$1" + bup -d "$(bup_local)" ls -r "$backup_dir" "$BACKUP_NAME" | sort -r } function bup_ls_all() { - for BACKUP_DIR in ${BACKUP_DIRS[*]} + for backup_dir in ${BACKUP_DIRS[*]} do echo "bup: backups in \"$BACKUP_DIR\":" - bup -d "$(bup_local)" ls -r "$BACKUP_DIR" --human-readable -l "$BACKUP_NAME" + bup -d "$(bup_local)" ls -r "$backup_dir" --human-readable -l "$BACKUP_NAME" done } function bup_restore() { - REMOTE="$1" - SNAPSHOT="$2" - - bup -d "$(bup_local)" restore -r "$REMOTE" "$BACKUP_NAME/$SNAPSHOT/$PWD/." + local remote="$1" + local snapshot="$2" + bup -d "$(bup_local)" restore -r "$remote" "$BACKUP_NAME/$snapshot/$PWD/." } diff --git a/backends/tar.sh b/backends/tar.sh index 1265992..f7ea86e 100644 --- a/backends/tar.sh +++ b/backends/tar.sh @@ -7,68 +7,74 @@ function tar_init() { function tar_create_backup() { echo "tar: backing up..." - # save world to a temporary archive - ARCHNAME="/tmp/${BACKUP_NAME}_`date +%FT%H%M%S%z`.tar.gz" - tar -czf "$ARCHNAME" "./$WORLD_NAME" + local status - if [ ! $? -eq 0 ] - then + # save world to a temporary archive + local archname="/tmp/${BACKUP_NAME}_`date +%FT%H%M%S%z`.tar.gz" + tar -czf "$archname" "./$WORLD_NAME" + status=$? + if [ $status -ne 0 ]; then echo "tar: failed to save the world" - rm "$ARCHNAME" #remove (probably faulty) archive + rm "$archname" #remove (probably faulty) archive return 1 - else - echo "tar: world saved to $ARCHNAME, pushing it to backup directories..." fi + echo "tar: world saved to $archname, pushing it to backup directories..." - RETCODE=2 - for BACKUP_DIR in ${BACKUP_DIRS[*]} + # 0 if could save to at least one backup dir + # TODO: make more strict? + local retcode=1 + for backup_dir in ${BACKUP_DIRS[*]} do - echo "tar: pushing to \"$BACKUP_DIR\"" + echo "tar: pushing to \"$backup_dir\"" # scp acts as cp for local destination directories - scp "$ARCHNAME" "$BACKUP_DIR/" - if [ ! $? -eq 0 ]; then - echo "tar: failed pushing to \"$BACKUP_DIR\", moving on" + scp "$archname" "$backup_dir/" + status=$? + if [ $status -ne 0 ]; then + echo "tar: failed pushing to \"$backup_dir\", moving on" else - RETCODE=0 + retcode=0 fi done - rm "$ARCHNAME" + rm "$archname" echo "tar: backup finished" - return $RETCODE + return $retcode } # server_restore relies on output format of this function function tar_ls_dir() { - BACKUP_DIR="$1" - if [[ $BACKUP_DIR == *:* ]]; then - REMOTE="$(echo "$BACKUP_DIR" | cut -d: -f1)" - REMOTE_DIR="$(echo "$BACKUP_DIR" | cut -d: -f2)" - ssh "$REMOTE" "ls -1 $REMOTE_DIR" | grep "tar.gz" + local backup_dir="$1" + + if [[ "$backup_dir" == *:* ]]; then + local remote="$(echo "$backup_dir" | cut -d: -f1)" + local remote_dir="$(echo "$backup_dir" | cut -d: -f2)" + ssh "$remote" "ls -1 $remote_dir" | grep "tar.gz" | sort -r else - ls -1 "$BACKUP_DIR" | grep "tar.gz" + ls -1 "$backup_dir" | grep "tar.gz" | sort -r fi } function tar_ls_all() { - for BACKUP_DIR in ${BACKUP_DIRS[*]} + for backup_dir in ${BACKUP_DIRS[*]} do - echo "Backups in $BACKUP_DIR:" - tar_ls_remote "$BACKUP_DIR" + echo "tar: backups in ${backup_dir}:" + tar_ls_remote "$backup_dir" done } function tar_restore() { - REMOTE="$1" - SNAPSHOT="$2" + local remote="$1" + local snapshot="$2" + local status - scp "$REMOTE/$SNAPSHOT" "/tmp/" - if [ ! $? -eq 0 ]; then - echo "Failed to get archive from \"$REMOTE/$SNAPSHOT\"" + scp "$remote/$snapshot" "/tmp/" + status=$? + if [ $status -ne 0 ]; then + echo "tar: failed to get archive from \"$remote/$snapshot\"" return 1 fi - tar -xzf "/tmp/$SNAPSHOT" + tar -xzf "/tmp/$snapshot" } diff --git a/server.sh b/server.sh index 46156af..ad1a7d8 100755 --- a/server.sh +++ b/server.sh @@ -111,14 +111,14 @@ function players_online() { } function init_backup() { - for BACKUP_DIR in ${BACKUP_DIRS[*]} + for backup_dir in ${BACKUP_DIRS[*]} do - if [[ $BACKUP_DIR == *:* ]]; then - REMOTE="$(echo "$BACKUP_DIR" | cut -d: -f1)" - REMOTE_DIR="$(echo "$BACKUP_DIR" | cut -d: -f2)" - ssh "$REMOTE" "mkdir -p \"$REMOTE_DIR\"" + if [[ $backup_dir == *:* ]]; then + local remote="$(echo "$backup_dir" | cut -d: -f1)" + local remote_dir="$(echo "$backup_dir" | cut -d: -f2)" + ssh "$remote" "mkdir -p \"$remote_dir\"" else - mkdir -p "$BACKUP_DIR" + mkdir -p "$backup_dir" fi done @@ -144,7 +144,7 @@ function create_backup() { } function server_backup_safe() { - force=$1 + local force=$1 echo "Detected running server. Checking if players online..." if [ "$force" != "true" ] && ! players_online; then echo "Players are not online. Not backing up." @@ -171,8 +171,7 @@ function server_backup_safe() { echo "Re-enabling auto-save" send_cmd "save-on" - if [ $RET -eq 0 ] - then + if [ $RET -eq 0 ]; then echo Running backup hook $BACKUP_HOOK fi @@ -182,9 +181,9 @@ function server_backup_unsafe() { echo "No running server detected. Running Backup" create_backup + local status=$? - if [ $? -eq 0 ] - then + if [ $status -eq 0 ]; then echo Running backup hook $BACKUP_HOOK fi @@ -199,7 +198,7 @@ function fbackup_running() { } function server_backup() { - force=$1 + local force=$1 if [ "$force" = "true" ]; then if backup_running; then @@ -218,8 +217,6 @@ function server_backup() { else server_backup_unsafe fi - - exit } function ls_backups() { @@ -232,6 +229,7 @@ function ls_backups() { fi } +# creates a selection dialog function choose_from() { local items=("$@") select item in "${items[@]}"; do @@ -241,60 +239,102 @@ function choose_from() { echo "" } +# checks if an item is in the array +function is_in() { + local item="$1" + shift + local array=("$@") + + # these :space: things allow checking that *exactly* this item is in array + if [[ ${array[*]} =~ (^|[[:space:]])"$item"($|[[:space:]]) ]]; then + return + fi + false +} + function server_restore() { - echo "Select from where get the snapshot" - BACKUP_DIR=$(choose_from "${BACKUP_DIRS[@]}") - if [[ ! ${BACKUP_DIRS[*]} =~ (^|[[:space:]])"$BACKUP_DIR"($|[[:space:]]) ]]; then + local backup_dir + local snapshot_index + local dest + + if [ $# -ge 2 ]; then + backup_dir="$1" + snapshot_index=$2 + fi + + if [ $# -eq 3 ]; then + dest="$3" + fi + + if [ ${#BACKUP_DIRS[@]} -eq 0 ]; then + echo "No backup directories found, abort" + return 1 + fi + if [ -z $backup_dir ]; then + echo "From where get the snapshot?" + backup_dir="$(choose_from "${BACKUP_DIRS[@]}")" + else + backup_dir=${BACKUP_DIRS[backup_dir_index]} + fi + if ! is_in "$backup_dir" "${BACKUP_DIRS[@]}" ; then echo "No valid backup directory selected, abort" return 1 fi - SNAPSHOTS=$( + local snapshots=$( if [ $BACKUP_BACKEND = "bup" ]; then - bup_ls_dir "$BACKUP_DIR" + bup_ls_dir "$backup_dir" elif [ $BACKUP_BACKEND = "borg" ]; then - borg_ls_dir "$BACKUP_DIR" + borg_ls_dir "$backup_dir" else - tar_ls_dir "$BACKUP_DIR" + tar_ls_dir "$backup_dir" fi ) - if [ -z "$SNAPSHOTS" ]; then + if [ -z "$snapshots" ]; then echo "No snapshots found, abort" return 1 fi # convert multiline string to bash array - SNAPSHOTS=($(echo "$SNAPSHOTS")) - echo "Select a snapshot to restore" - SNAPSHOT=$(choose_from "${SNAPSHOTS[@]}") - if [[ ! ${SNAPSHOTS[*]} =~ (^|[[:space:]])"$SNAPSHOT"($|[[:space:]]) ]]; then + snapshots=($(echo "$snapshots")) + + local snapshot + if [ -z $snapshot_index ]; then + echo "Select which snapshot to restore" + snapshot=$(choose_from "${snapshots[@]}") + else + snapshot="${snapshots[snapshot_index]}" + fi + if ! is_in "$snapshot" "${snapshots[@]}" ; then echo "No valid snapshot selected, abort" return 1 fi - echo "Restoring snapshot \"$SNAPSHOT\" from \"$BACKUP_DIR\"" + echo "Restoring snapshot \"$snapshot\" from \"$backup_dir\"" - OLDWORLD_NAME="" + local oldworld_name="" if [[ -d "$WORLD_NAME" ]]; then - echo "Saving old world, just in case" - OLDWORLD_NAME="${WORLD_NAME}.old.$(date +'%F_%H-%M-%S')" - mv -v "$WORLD_NAME" "$OLDWORLD_NAME" + echo -n "Preserving old world: " + oldworld_name="${WORLD_NAME}.old.$(date +'%F_%H-%M-%S')" + mv -v "$PWD/$WORLD_NAME" "$PWD/$oldworld_name" fi if [ $BACKUP_BACKEND = "bup" ]; then - bup_restore "$BACKUP_DIR" "$SNAPSHOT" + bup_restore "$backup_dir" "$snapshot" elif [ $BACKUP_BACKEND = "borg" ]; then - borg_restore "$BACKUP_DIR" "$SNAPSHOT" + borg_restore "$backup_dir" "$snapshot" else - tar_restore "$BACKUP_DIR" "$SNAPSHOT" + tar_restore "$backup_dir" "$snapshot" fi - - if [ ! $? -eq 0 ]; then - echo "Restore failed, reverting old world back" - rm -r "$WORLD_NAME" - mv -v "$OLDWORLD_NAME" "$WORLD_NAME" - else - echo "Restore finished" + local status=$? + if [ $status -ne 0 ]; then + echo "Failed to restore snapshot, putting old world back where it was:" + rm -rv "$PWD/$WORLD_NAME" + mv -v "$PWD/$oldworld_name" "$PWD/$WORLD_NAME" + return 1 fi + echo "Snapshot restored" + + return 0 } #cd $(dirname $0) -- cgit v1.2.3