From f7829e550034b8ee27789e165f3faf75cc29b729 Mon Sep 17 00:00:00 2001 From: Nicolas Chan Date: Thu, 4 Mar 2021 14:11:11 -0800 Subject: [PATCH] Better error handling --- backup.sh | 80 ++++++++++++++++++++++++++++------------------------ test/test.sh | 14 ++++++--- 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/backup.sh b/backup.sh index 4100f73..6f68c52 100755 --- a/backup.sh +++ b/backup.sh @@ -177,7 +177,10 @@ rcon-command () { # Open a TCP socket # Source: https://www.xmodulo.com/tcp-udp-socket-bash-shell.html - exec 3<>/dev/tcp/"$HOST"/"$PORT" + if ! exec 3<>/dev/tcp/"$HOST"/"$PORT"; then + log-warning "RCON connection failed: Could not connect to $HOST:$PORT" + return 1 + fi login "$PASSWORD" || return 1 debug-log "$(run-command "$COMMAND")" @@ -371,6 +374,44 @@ delete-thinning () { delete-sequentially } +# Delete old backups +delete-old-backups () { + case $DELETE_METHOD in + "sequential") delete-sequentially + ;; + "thin") delete-thinning + ;; + esac +} + +clean-up () { + # Re-enable world autosaving + execute-command "save-on" + + # Save the world + execute-command "save-all" + + # Notify players of completion + WORLD_SIZE_BYTES=$(du -b --max-depth=0 "$SERVER_WORLD" | awk '{print $1}') + ARCHIVE_SIZE_BYTES=$(du -b "$ARCHIVE_PATH" | awk '{print $1}') + ARCHIVE_SIZE=$(du -h "$ARCHIVE_PATH" | awk '{print $1}') + BACKUP_DIRECTORY_SIZE=$(du -h --max-depth=0 "$BACKUP_DIRECTORY" | awk '{print $1}') + TIME_DELTA=$((END_TIME - START_TIME)) + + # Check that archive size is not null and at least 200 Bytes + if [[ "$ARCHIVE_EXIT_CODE" == "0" && "$WORLD_SIZE_BYTES" -gt 0 && "$ARCHIVE_SIZE" != "" && "$ARCHIVE_SIZE_BYTES" -gt 200 ]]; then + COMPRESSION_PERCENT=$((ARCHIVE_SIZE_BYTES * 100 / WORLD_SIZE_BYTES)) + message-players-success "Backup complete!" "$TIME_DELTA s, $ARCHIVE_SIZE/$BACKUP_DIRECTORY_SIZE, $COMPRESSION_PERCENT%" + delete-old-backups + exit 0 + else + message-players-error "Backup was not saved!" "Please notify an administrator" + exit 1 + fi +} + +trap "clean-up" 2 + # Ensure backup directory exists mkdir -p "$(dirname "$ARCHIVE_PATH")" @@ -394,39 +435,4 @@ fi sync END_TIME=$(date +"%s") -# Enable world autosaving -execute-command "save-on" - -# Save the world -execute-command "save-all" - -# Delete old backups -delete-old-backups () { - case $DELETE_METHOD in - "sequential") delete-sequentially - ;; - "thin") delete-thinning - ;; - esac -} - -# Notify players of completion -WORLD_SIZE_BYTES=$(du -b --max-depth=0 "$SERVER_WORLD" | awk '{print $1}') -ARCHIVE_SIZE_BYTES=$(du -b "$ARCHIVE_PATH" | awk '{print $1}') -ARCHIVE_SIZE=$(du -h "$ARCHIVE_PATH" | awk '{print $1}') -BACKUP_DIRECTORY_SIZE=$(du -h --max-depth=0 "$BACKUP_DIRECTORY" | awk '{print $1}') -TIME_DELTA=$((END_TIME - START_TIME)) - -# Check that archive size is not null and at least 200 Bytes -if [[ "$ARCHIVE_EXIT_CODE" -eq 0 && "$WORLD_SIZE_BYTES" -gt 0 && "$ARCHIVE_SIZE" != "" && "$ARCHIVE_SIZE_BYTES" -gt 200 ]]; then - COMPRESSION_PERCENT=$((ARCHIVE_SIZE_BYTES * 100 / WORLD_SIZE_BYTES)) - message-players-success "Backup complete!" "$TIME_DELTA s, $ARCHIVE_SIZE/$BACKUP_DIRECTORY_SIZE, $COMPRESSION_PERCENT%" - delete-old-backups -else - message-players-error "Backup was not saved!" "Please notify an administrator" - if [ "$ARCHIVE_EXIT_CODE" -ne 0 ]; then - exit "$ARCHIVE_EXIT_CODE" - else - exit 1 - fi -fi +clean-up \ No newline at end of file diff --git a/test/test.sh b/test/test.sh index be699ac..62d0180 100755 --- a/test/test.sh +++ b/test/test.sh @@ -23,7 +23,7 @@ setUp () { echo "$!" > "$TEST_TMP/rcon-pid" while ! [[ (-f "$TEST_TMP/screen-output") && (-f "$TEST_TMP/tmux-output") && (-f "$TEST_TMP/rcon-output") ]]; do - sleep 0.2 + sleep 0.3 done } @@ -159,7 +159,7 @@ test-screen-interface () { ./backup.sh -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP" EXPECTED_CONTENTS=$(echo -e "save-off\nsave-on\nsave-all") SCREEN_CONTENTS="$(cat "$TEST_TMP/screen-output")" - assertEquals "$SCREEN_CONTENTS" "$EXPECTED_CONTENTS" + assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } test-tmux-interface () { @@ -167,7 +167,7 @@ test-tmux-interface () { ./backup.sh -w tmux -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP" EXPECTED_CONTENTS=$(echo -e "save-off\nsave-on\nsave-all") SCREEN_CONTENTS="$(cat "$TEST_TMP/tmux-output")" - assertEquals "$SCREEN_CONTENTS" "$EXPECTED_CONTENTS" + assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } test-rcon-interface () { @@ -175,7 +175,7 @@ test-rcon-interface () { ./backup.sh -w rcon -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "localhost:$RCON_PORT:$RCON_PASSWORD" -f "$TIMESTAMP" EXPECTED_CONTENTS=$(echo -e "save-off\nsave-on\nsave-all") SCREEN_CONTENTS="$(head -n3 "$TEST_TMP/rcon-output")" - assertEquals "$SCREEN_CONTENTS" "$EXPECTED_CONTENTS" + assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } test-rcon-interface-wrong-password () { @@ -184,6 +184,12 @@ test-rcon-interface-wrong-password () { assertContains "$OUTPUT" "Wrong RCON password" } +test-rcon-interface-not-running () { + TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" + OUTPUT="$(./backup.sh -w RCON -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "@!@#:$RCON_PORT:$RCON_PASSWORD" -f "$TIMESTAMP" 2>&1)" + assertContains "$OUTPUT" "Could not connect" +} + test-sequential-delete () { for i in $(seq 0 99); do TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01 +$i hour")"