Merge pull request #22 from tleibert/spigot-paper-compatibility

spigot/paper worldnaming compatibility
This commit is contained in:
Nicolas Chan 2021-06-03 21:00:42 -07:00 committed by GitHub
commit 7824c8c694
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 37 deletions

View file

@ -56,7 +56,7 @@ Command line options:
-e Compression file extension, exclude leading "." (default: gz) -e Compression file extension, exclude leading "." (default: gz)
-f Output file name (default is the timestamp) -f Output file name (default is the timestamp)
-h Shows this help text -h Shows this help text
-i Input directory (path to world folder) -i Input directory (path to world folder, use -i once for each world)
-l Compression level (default: 3) -l Compression level (default: 3)
-m Maximum backups to keep, use -1 for unlimited (default: 128) -m Maximum backups to keep, use -1 for unlimited (default: 128)
-o Output directory -o Output directory
@ -87,7 +87,7 @@ cd restored-world
tar -xzvf /path/to/backups/2019-04-09_02-15-01.tar.gz tar -xzvf /path/to/backups/2019-04-09_02-15-01.tar.gz
``` ```
Then you can move your restored world (`restored-world` in this case) to your Minecraft server folder and rename it (usually called `world`) so the Minecraft server uses it. The restored worlds should be inside the `restored-world` directory, possibly nested under the parent directories. Then you can move your restored world to your Minecraft server folder under the proper name and path so the Minecraft server uses it.
### With `restic` ### With `restic`
Use [`restic restore`](https://restic.readthedocs.io/en/latest/050_restore.html) to restore from backup. Use [`restic restore`](https://restic.readthedocs.io/en/latest/050_restore.html) to restore from backup.

View file

@ -9,7 +9,7 @@
# Default Configuration # Default Configuration
SCREEN_NAME="" # Name of the GNU Screen, tmux session, or hostname:port:password for RCON SCREEN_NAME="" # Name of the GNU Screen, tmux session, or hostname:port:password for RCON
SERVER_WORLD="" # Server world directory SERVER_WORLDS=() # Server world directory
BACKUP_DIRECTORY="" # Directory to save backups in BACKUP_DIRECTORY="" # Directory to save backups in
MAX_BACKUPS=128 # -1 indicates unlimited MAX_BACKUPS=128 # -1 indicates unlimited
DELETE_METHOD="thin" # Choices: thin, sequential, none; sequential: delete oldest; thin: keep last 24 hourly, last 30 daily, and monthly (use with 1 hr cron interval) DELETE_METHOD="thin" # Choices: thin, sequential, none; sequential: delete oldest; thin: keep last 24 hourly, last 30 daily, and monthly (use with 1 hr cron interval)
@ -40,7 +40,7 @@ debug-log () {
fi fi
} }
while getopts 'a:cd:e:f:hi:l:m:o:p:qr:s:t:u:vw:' FLAG; do while getopts 'a:cd:e:f:hi:l:m:o:p:qr:s:t:u:vw:x' FLAG; do
case $FLAG in case $FLAG in
a) COMPRESSION_ALGORITHM=$OPTARG ;; a) COMPRESSION_ALGORITHM=$OPTARG ;;
c) ENABLE_CHAT_MESSAGES=true ;; c) ENABLE_CHAT_MESSAGES=true ;;
@ -55,7 +55,7 @@ while getopts 'a:cd:e:f:hi:l:m:o:p:qr:s:t:u:vw:' FLAG; do
echo "-e Compression file extension, exclude leading \".\" (default: gz)" echo "-e Compression file extension, exclude leading \".\" (default: gz)"
echo "-f Output file name (default is the timestamp)" echo "-f Output file name (default is the timestamp)"
echo "-h Shows this help text" echo "-h Shows this help text"
echo "-i Input directory (path to world folder)" echo "-i Input directory (path to world folder, use -i once for each world)"
echo "-l Compression level (default: 3)" echo "-l Compression level (default: 3)"
echo "-m Maximum backups to keep, use -1 for unlimited (default: 128)" echo "-m Maximum backups to keep, use -1 for unlimited (default: 128)"
echo "-o Output directory" echo "-o Output directory"
@ -67,9 +67,10 @@ while getopts 'a:cd:e:f:hi:l:m:o:p:qr:s:t:u:vw:' FLAG; do
echo "-u Lock file timeout seconds (empty = unlimited)" echo "-u Lock file timeout seconds (empty = unlimited)"
echo "-v Verbose mode" echo "-v Verbose mode"
echo "-w Window manager: screen (default), tmux, RCON" echo "-w Window manager: screen (default), tmux, RCON"
echo "-x Bukkit-style server backup mode (world files are split by dimension)"
exit 0 exit 0
;; ;;
i) SERVER_WORLD=$OPTARG ;; i) SERVER_WORLDS+=("$OPTARG") ;;
l) COMPRESSION_LEVEL=$OPTARG ;; l) COMPRESSION_LEVEL=$OPTARG ;;
m) MAX_BACKUPS=$OPTARG ;; m) MAX_BACKUPS=$OPTARG ;;
o) BACKUP_DIRECTORY=$OPTARG ;; o) BACKUP_DIRECTORY=$OPTARG ;;
@ -216,7 +217,7 @@ if ! $SUPPRESS_WARNINGS; then
fi fi
# Check for required arguments # Check for required arguments
MISSING_CONFIGURATION=false MISSING_CONFIGURATION=false
if [[ "$SERVER_WORLD" == "" ]]; then if [[ "${#SERVER_WORLDS[@]}" == "0" ]]; then
log-fatal "Server world not specified (use -i)" log-fatal "Server world not specified (use -i)"
MISSING_CONFIGURATION=true MISSING_CONFIGURATION=true
fi fi
@ -442,7 +443,7 @@ clean-up () {
TIME_DELTA=$((END_TIME - START_TIME)) TIME_DELTA=$((END_TIME - START_TIME))
if [[ "$BACKUP_DIRECTORY" != "" ]]; then if [[ "$BACKUP_DIRECTORY" != "" ]]; then
WORLD_SIZE_BYTES=$(du -b --max-depth=0 "$SERVER_WORLD" | awk '{print $1}') WORLD_SIZE_BYTES=$(du --bytes --total --max-depth=0 "${SERVER_WORLDS[@]}" | tail -n 1 | awk '{print $1}')
ARCHIVE_SIZE_BYTES=$(du -b "$ARCHIVE_PATH" | awk '{print $1}') ARCHIVE_SIZE_BYTES=$(du -b "$ARCHIVE_PATH" | awk '{print $1}')
ARCHIVE_SIZE=$(du -h "$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}') BACKUP_DIRECTORY_SIZE=$(du -h --max-depth=0 "$BACKUP_DIRECTORY" | awk '{print $1}')
@ -491,10 +492,10 @@ do-backup () {
case $COMPRESSION_ALGORITHM in case $COMPRESSION_ALGORITHM in
# No compression # No compression
"") tar -cf "$ARCHIVE_PATH" -C "$SERVER_WORLD" . "") tar -cf "$ARCHIVE_PATH" "${SERVER_WORLDS[@]}"
;; ;;
# With compression # With compression
*) tar -cf - -C "$SERVER_WORLD" . | $COMPRESSION_ALGORITHM -cv -"$COMPRESSION_LEVEL" - > "$ARCHIVE_PATH" 2>> /dev/null *) tar -cf - "${SERVER_WORLDS[@]}" | $COMPRESSION_ALGORITHM -cv -"$COMPRESSION_LEVEL" - > "$ARCHIVE_PATH" 2>> /dev/null
;; ;;
esac esac
EXIT_CODES=("${PIPESTATUS[@]}") EXIT_CODES=("${PIPESTATUS[@]}")
@ -516,7 +517,7 @@ do-backup () {
if [[ "$RESTIC_REPO" != "" ]]; then if [[ "$RESTIC_REPO" != "" ]]; then
RESTIC_TIMESTAMP="${TIMESTAMP:0:10} ${TIMESTAMP:11:2}:${TIMESTAMP:14:2}:${TIMESTAMP:17:2}" RESTIC_TIMESTAMP="${TIMESTAMP:0:10} ${TIMESTAMP:11:2}:${TIMESTAMP:14:2}:${TIMESTAMP:17:2}"
restic backup -r "$RESTIC_REPO" "$SERVER_WORLD" --time "$RESTIC_TIMESTAMP" "$QUIET" restic backup -r "$RESTIC_REPO" "${SERVER_WORLDS[@]}" --time "$RESTIC_TIMESTAMP" "$QUIET"
ARCHIVE_EXIT_CODE=$? ARCHIVE_EXIT_CODE=$?
if [ "$ARCHIVE_EXIT_CODE" -eq 3 ]; then if [ "$ARCHIVE_EXIT_CODE" -eq 3 ]; then
log-warning "Incomplete snapshot taken (some files could not be read)" log-warning "Incomplete snapshot taken (some files could not be read)"

View file

@ -62,7 +62,7 @@ check-backup-full-paths () {
WORLD_DIR="$2" WORLD_DIR="$2"
mkdir -p "$TEST_TMP/restored" mkdir -p "$TEST_TMP/restored"
tar --extract --file "$BACKUP_ARCHIVE" --directory "$TEST_TMP/restored" tar --extract --file "$BACKUP_ARCHIVE" --directory "$TEST_TMP/restored"
assert-equals-directory "$WORLD_DIR" "$TEST_TMP/restored" assert-equals-directory "$WORLD_DIR" "$TEST_TMP/restored/$WORLD_DIR"
rm -rf "$TEST_TMP/restored" rm -rf "$TEST_TMP/restored"
} }
@ -80,6 +80,46 @@ check-latest-backup-restic () {
# Tests # Tests
test-backup-defaults () {
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"
check-backup "$TIMESTAMP.tar.gz"
}
test-backup-multiple-worlds () {
TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")"
cp -r "$TEST_TMP/server/world" "$TEST_TMP/server/world_nether"
cp -r "$TEST_TMP/server/world" "$TEST_TMP/server/world_the_end"
./backup.sh -i "$TEST_TMP/server/world" -i "$TEST_TMP/server/world_nether" -i "$TEST_TMP/server/world_the_end" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP"
mkdir -p "$TEST_TMP/restored"
tar --extract --file "$TEST_TMP/backups/$TIMESTAMP.tar.gz" --directory "$TEST_TMP/restored"
assert-equals-directory "$TEST_TMP/server/world" "$TEST_TMP/restored/$TEST_TMP/server/world"
assert-equals-directory "$TEST_TMP/server/world_nether" "$TEST_TMP/restored/$TEST_TMP/server/world_nether"
assert-equals-directory "$TEST_TMP/server/world_the_end" "$TEST_TMP/restored/$TEST_TMP/server/world_the_end"
}
test-file-changed-as-read-warning () {
TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")"
dd if=/dev/urandom of="$TEST_TMP/server/world/random" &
DD_PID="$!"
OUTPUT="$(./backup.sh -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP" 2>&1)"
EXIT_CODE="$?"
kill "$DD_PID"
assertEquals 0 "$EXIT_CODE"
assertContains "$OUTPUT" "Some files may differ in the backup archive"
# Check that the backup actually resulted in a valid tar
assertTrue '[ -f '"$TEST_TMP/backups/$TIMESTAMP.tar.gz"' ]'
mkdir -p "$TEST_TMP/restored"
tar --extract --file "$TEST_TMP/backups/$TIMESTAMP.tar.gz" --directory "$TEST_TMP/restored"
assert-equals-directory "$WORLD_DIR/file1.txt" "$TEST_TMP/restored/$WORLD_DIR/file1.txt"
assert-equals-directory "$WORLD_DIR/file2.txt" "$TEST_TMP/restored/$WORLD_DIR/file2.txt"
assert-equals-directory "$WORLD_DIR/file3.txt" "$TEST_TMP/restored/$WORLD_DIR/file3.txt"
}
test-lock-defaults () { test-lock-defaults () {
TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")"
./backup.sh -t "$TEST_TMP/lockfile" -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP" ./backup.sh -t "$TEST_TMP/lockfile" -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP"
@ -183,11 +223,6 @@ test-restic-defaults () {
check-latest-backup-restic check-latest-backup-restic
} }
test-backup-defaults () {
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"
check-backup "$TIMESTAMP.tar.gz"
}
test-backup-spaces-in-directory () { test-backup-spaces-in-directory () {
TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")"
@ -293,26 +328,6 @@ test-nonzero-exit-warning () {
assertFalse '[ -f '"$TEST_TMP/backups/$TIMESTAMP.tar.gz"' ]' assertFalse '[ -f '"$TEST_TMP/backups/$TIMESTAMP.tar.gz"' ]'
} }
test-file-changed-as-read-warning () {
TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")"
dd if=/dev/urandom of="$TEST_TMP/server/world/random" &
DD_PID="$!"
OUTPUT="$(./backup.sh -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP" 2>&1)"
EXIT_CODE="$?"
kill "$DD_PID"
assertEquals 0 "$EXIT_CODE"
assertContains "$OUTPUT" "Some files may differ in the backup archive"
# Check that the backup actually resulted in a valid tar
assertTrue '[ -f '"$TEST_TMP/backups/$TIMESTAMP.tar.gz"' ]'
mkdir -p "$TEST_TMP/restored"
tar --extract --file "$TEST_TMP/backups/$TIMESTAMP.tar.gz" --directory "$TEST_TMP/restored"
assert-equals-directory "$WORLD_DIR/file1.txt" "$TEST_TMP/restored/file1.txt"
assert-equals-directory "$WORLD_DIR/file2.txt" "$TEST_TMP/restored/file2.txt"
assert-equals-directory "$WORLD_DIR/file3.txt" "$TEST_TMP/restored/file3.txt"
}
test-screen-interface () { test-screen-interface () {
TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" 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" ./backup.sh -i "$TEST_TMP/server/world" -o "$TEST_TMP/backups" -s "$SCREEN_TMP" -f "$TIMESTAMP"