From f141d73bc2aa86350da949ee4b731a1a66d4f334 Mon Sep 17 00:00:00 2001 From: Nicolas Chan Date: Wed, 6 Aug 2025 00:12:57 -0700 Subject: [PATCH 1/4] Run save-all before save-off --- backup.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backup.sh b/backup.sh index af4ad58..22f019c 100755 --- a/backup.sh +++ b/backup.sh @@ -489,6 +489,9 @@ do-backup () { # Notify players of start message-players "Starting backup..." "$ARCHIVE_PATH" + # Trigger save now to get most up-to-date data + execute-command "save-all" + # Disable world autosaving execute-command "save-off" From 637057567fbcac379d3957656518161c381b33da Mon Sep 17 00:00:00 2001 From: Nicolas Chan Date: Wed, 6 Aug 2025 00:15:46 -0700 Subject: [PATCH 2/4] Switch to old ubuntu for kcov --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2249490..e2e5913 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ on: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 with: @@ -28,7 +28,7 @@ jobs: - name: Run tests run: test/test.sh coverage: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 with: From 238b0240442dc6159ebe213f393a4eeeac0e2ea6 Mon Sep 17 00:00:00 2001 From: Nicolas Chan Date: Wed, 6 Aug 2025 01:12:01 -0700 Subject: [PATCH 3/4] Switch to save-all flush and update tests --- backup.sh | 2 +- test/data/test-chat-messages.txt | 1 + test/data/test-chat-prefix.txt | 1 + test/test.sh | 8 ++++---- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/backup.sh b/backup.sh index 22f019c..91d06e4 100755 --- a/backup.sh +++ b/backup.sh @@ -490,7 +490,7 @@ do-backup () { message-players "Starting backup..." "$ARCHIVE_PATH" # Trigger save now to get most up-to-date data - execute-command "save-all" + execute-command "save-all flush" # Disable world autosaving execute-command "save-off" diff --git a/test/data/test-chat-messages.txt b/test/data/test-chat-messages.txt index 65aaeb4..df4a68b 100644 --- a/test/data/test-chat-messages.txt +++ b/test/data/test-chat-messages.txt @@ -1,4 +1,5 @@ tellraw @a ["",{"text":"[Backup] ","color":"gray","italic":true},{"text":"Starting backup...","color":"gray","italic":true,"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"test/tmp/backups/2021-01-01_00-00-00.tar.gz"}]}}}] +save-all flush save-off save-on save-all diff --git a/test/data/test-chat-prefix.txt b/test/data/test-chat-prefix.txt index 33d6856..daf8b98 100644 --- a/test/data/test-chat-prefix.txt +++ b/test/data/test-chat-prefix.txt @@ -1,4 +1,5 @@ tellraw @a ["",{"text":"[Hello] ","color":"gray","italic":true},{"text":"Starting backup...","color":"gray","italic":true,"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"test/tmp/backups/2021-01-01_00-00-00.tar.gz"}]}}}] +save-all flush save-off save-on save-all diff --git a/test/test.sh b/test/test.sh index 42a2991..5536056 100755 --- a/test/test.sh +++ b/test/test.sh @@ -346,7 +346,7 @@ test-nonzero-exit-warning () { test-screen-interface () { TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" ./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") + EXPECTED_CONTENTS=$(echo -e "save-all flush\nsave-off\nsave-on\nsave-all") SCREEN_CONTENTS="$(cat "$TEST_TMP/screen-output")" assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } @@ -354,7 +354,7 @@ test-screen-interface () { test-tmux-interface () { TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" ./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") + EXPECTED_CONTENTS=$(echo -e "save-all flush\nsave-off\nsave-on\nsave-all") SCREEN_CONTENTS="$(cat "$TEST_TMP/tmux-output")" assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } @@ -362,8 +362,8 @@ test-tmux-interface () { test-rcon-interface () { TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" ./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")" + EXPECTED_CONTENTS=$(echo -e "save-all flush\nsave-off\nsave-on\nsave-all") + SCREEN_CONTENTS="$(head -n4 "$TEST_TMP/rcon-output")" assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } From 4f675b9357e0e8d8fae9b5ff6837feaa9737f2e9 Mon Sep 17 00:00:00 2001 From: Nicolas Chan Date: Wed, 6 Aug 2025 10:27:46 -0700 Subject: [PATCH 4/4] Add save-all delay option --- backup.sh | 32 +++++++++++++++++++++++++++----- test/data/test-chat-messages.txt | 3 ++- test/data/test-chat-prefix.txt | 3 ++- test/test.sh | 8 ++++---- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/backup.sh b/backup.sh index 91d06e4..84a90e1 100755 --- a/backup.sh +++ b/backup.sh @@ -24,6 +24,7 @@ RESTIC_HOSTNAME="" # Leave empty to use system hostname LOCK_FILE="" # Optional lock file to acquire to ensure two backups don't run at once LOCK_FILE_TIMEOUT="" # Optional lock file wait timeout (in seconds) WINDOW_MANAGER="screen" # Choices: screen, tmux, RCON +SAVE_ALL_WAIT_SECONDS="" # Delay in seconds after save-all flush (default: 5, 0 if rcon) # Other Variables (do not modify) DATE_FORMAT="%F_%H-%M-%S" @@ -41,7 +42,7 @@ debug-log () { fi } -while getopts 'a:cd:e:f:hH:i:l:m:o:p:qr:s:t:u:vw:x' FLAG; do +while getopts 'a:cd:e:f:hH:i:l:m:o:p:qr:s:t:u:vw:xz:' FLAG; do case $FLAG in a) COMPRESSION_ALGORITHM=$OPTARG ;; c) ENABLE_CHAT_MESSAGES=true ;; @@ -69,6 +70,7 @@ while getopts 'a:cd:e:f:hH:i:l:m:o:p:qr:s:t:u:vw:x' FLAG; do echo "-u Lock file timeout seconds (empty = unlimited)" echo "-v Verbose mode" echo "-w Window manager: screen (default), tmux, RCON" + echo "-z Delay in seconds after save-all flush (default: 5, 0 if rcon)" exit 0 ;; H) RESTIC_HOSTNAME=$OPTARG ;; @@ -84,6 +86,7 @@ while getopts 'a:cd:e:f:hH:i:l:m:o:p:qr:s:t:u:vw:x' FLAG; do u) LOCK_FILE_TIMEOUT=$OPTARG ;; v) DEBUG=true ;; w) WINDOW_MANAGER=$OPTARG ;; + z) SAVE_ALL_WAIT_SECONDS=$OPTARG ;; *) log-fatal "Invalid option -$FLAG"; exit 1 ;; esac done @@ -290,6 +293,25 @@ message-players-color () { execute-command "tellraw @a [\"\",{\"text\":\"[$PREFIX] \",\"color\":\"gray\",\"italic\":true},{\"text\":\"$MESSAGE\",\"color\":\"$COLOR\",\"italic\":true,\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"$HOVER_MESSAGE\"}]}}}]" fi } +save-all-flush-delay-seconds () { + if [[ -n "$SAVE_ALL_WAIT_SECONDS" ]]; then + echo "$SAVE_ALL_WAIT_SECONDS" + return + fi + + case "$WINDOW_MANAGER" in + # RCON already waits for response + "RCON"|"rcon"|"docker-rcon") echo "0" + ;; + *) echo "5" # default value for all other cases + ;; + esac +} +execute-save-all-flush () { + execute-command "save-all" # for versions <1.16 + execute-command "save-all flush" + sleep "$(save-all-flush-delay-seconds)" +} # Parse file timestamp to one readable by "date" parse-file-timestamp () { @@ -489,12 +511,12 @@ do-backup () { # Notify players of start message-players "Starting backup..." "$ARCHIVE_PATH" - # Trigger save now to get most up-to-date data - execute-command "save-all flush" - - # Disable world autosaving + # Disable world autosaving, still allows save-all execute-command "save-off" + # Trigger save now to get most up-to-date data + execute-save-all-flush + # Backup world START_TIME=$(date +"%s") diff --git a/test/data/test-chat-messages.txt b/test/data/test-chat-messages.txt index df4a68b..75615f1 100644 --- a/test/data/test-chat-messages.txt +++ b/test/data/test-chat-messages.txt @@ -1,6 +1,7 @@ tellraw @a ["",{"text":"[Backup] ","color":"gray","italic":true},{"text":"Starting backup...","color":"gray","italic":true,"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"test/tmp/backups/2021-01-01_00-00-00.tar.gz"}]}}}] -save-all flush save-off +save-all +save-all flush save-on save-all tellraw @a ["",{"text":"[Backup] ","color":"gray","italic":true},{"text":"Backup complete!","color":"green","italic":true,"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"0 s, 4.0K/4.0K, 316%"}]}}}] diff --git a/test/data/test-chat-prefix.txt b/test/data/test-chat-prefix.txt index daf8b98..4b512e6 100644 --- a/test/data/test-chat-prefix.txt +++ b/test/data/test-chat-prefix.txt @@ -1,6 +1,7 @@ tellraw @a ["",{"text":"[Hello] ","color":"gray","italic":true},{"text":"Starting backup...","color":"gray","italic":true,"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"test/tmp/backups/2021-01-01_00-00-00.tar.gz"}]}}}] -save-all flush save-off +save-all +save-all flush save-on save-all tellraw @a ["",{"text":"[Hello] ","color":"gray","italic":true},{"text":"Hello complete!","color":"green","italic":true,"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"0 s, 4.0K/4.0K, 316%"}]}}}] diff --git a/test/test.sh b/test/test.sh index 5536056..7083909 100755 --- a/test/test.sh +++ b/test/test.sh @@ -346,7 +346,7 @@ test-nonzero-exit-warning () { test-screen-interface () { TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" ./backup.sh -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP" - EXPECTED_CONTENTS=$(echo -e "save-all flush\nsave-off\nsave-on\nsave-all") + EXPECTED_CONTENTS=$(echo -e "save-off\nsave-all\nsave-all flush\nsave-on\nsave-all") SCREEN_CONTENTS="$(cat "$TEST_TMP/screen-output")" assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } @@ -354,7 +354,7 @@ test-screen-interface () { test-tmux-interface () { TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" ./backup.sh -w tmux -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP" - EXPECTED_CONTENTS=$(echo -e "save-all flush\nsave-off\nsave-on\nsave-all") + EXPECTED_CONTENTS=$(echo -e "save-off\nsave-all\nsave-all flush\nsave-on\nsave-all") SCREEN_CONTENTS="$(cat "$TEST_TMP/tmux-output")" assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" } @@ -362,8 +362,8 @@ test-tmux-interface () { test-rcon-interface () { TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" ./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-all flush\nsave-off\nsave-on\nsave-all") - SCREEN_CONTENTS="$(head -n4 "$TEST_TMP/rcon-output")" + EXPECTED_CONTENTS=$(echo -e "save-off\nsave-all\nsave-all flush\nsave-on\nsave-all") + SCREEN_CONTENTS="$(head -n5 "$TEST_TMP/rcon-output")" assertEquals "$EXPECTED_CONTENTS" "$SCREEN_CONTENTS" }