Merge pull request #22 from tleibert/spigot-paper-compatibility
spigot/paper worldnaming compatibility
This commit is contained in:
commit
7824c8c694
3 changed files with 53 additions and 37 deletions
|
@ -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.
|
||||||
|
|
19
backup.sh
19
backup.sh
|
@ -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)"
|
||||||
|
|
67
test/test.sh
67
test/test.sh
|
@ -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"
|
||||||
|
|
Loading…
Add table
Reference in a new issue