ansible/roles/minecraft/files/minecraft-backup.sh

155 lines
3.1 KiB
Bash

#!/bin/bash
SERVICE=minecraft.service
BACKUP_DIR=/opt/minecraft/backup
VAR_DIR=/opt/minecraft/var
SCRATCH=$(mktemp -p /var/tmp -d minecraft.XXXXXXXXXX)
NICE=15
TAR=minecraft-$(date +%Y-%m-%d).tar
WAIT=30
VERBOSE=${VERBOSE:-4}
declare -A LOG_LEVELS
LOG_LEVELS=(
[emerg]=0
[alert]=1
[crit]=2
[err]=3
[warning]=4
[notice]=5
[info]=6
[debug]=7
)
log() {
local LEVEL
local TS
LEVEL=$1
TS="$(date -Is)"
shift
if [[ $VERBOSE -ge ${LOG_LEVELS[$LEVEL]} ]]; then
if [[ $# -ge 2 ]]; then
local FMT=$1
shift
printf "%s [%s] ${FMT}\n" "${TS}" "$LEVEL" "$@"
else
echo "${TS} [$LEVEL]" "$@"
fi
fi
}
finish() {
log info "Cleaning up"
rm -rf "$SCRATCH"
if ! systemctl -q is-active "$SERVICE"; then
start_server $SERVICE
fi
}
trap finish EXIT
error_exit() {
log crit "$1"
exit 1
}
stop_server() {
local unit="${1:-$SERVICE}"
local attempts="${2:-$WAIT}"
if ! systemctl -q is-active "$unit"; then
log warning "%s is already stopped\n" "$unit"
return 0
fi
systemctl -q stop "$unit"
while systemctl -q is-active "$unit"; do
log warning "Waiting for %s to stop ... (%s)\n" "$unit" "$attempts"
((attempts--))
if ((attempts == 0)); then
return 1
fi
sleep 1
done
return 0
}
start_server() {
local unit="${1:-$SERVICE}"
local attempts="${2:-$WAIT}"
if systemctl -q is-active "$unit"; then
log warning "%s is already started\n" "$unit"
return 0
fi
systemctl -q start "$unit"
while ! systemctl -q is-active "$unit"; do
log warning "Waiting for %s to start ... (%d)\n" "$unit" "$attempts"
((attempts--))
if ((attempts == 0)); then
return 1
fi
sleep 1
done
return 0
}
open_files() {
local dir=${1-$VAR_DIR}
local attempts="${2:-$WAIT}"
while (($(lsof +D "$dir" | wc -l) > 0)); do
log warning "Waiting for open files ... (%d)\n" "$attempts"
((attempts--))
if ((attempts == 0)); then
return 1
fi
sleep 1
done
return 0
}
main() {
log info "Stopping %s" $SERVICE
if ! stop_server $SERVICE; then
error_exit "Failed to stop $SERVICE"
fi
log info "Checking for open files"
if ! open_files $VAR_DIR; then
error_exit "Open files exist in $VAR_DIR"
fi
log info "Starting backup"
if ! tar -cf "$SCRATCH/$TAR" -C "$VAR_DIR" world; then
error_exit "Archive failed"
fi
log info "Starting %s" $SERVICE
if ! start_server $SERVICE; then
error_exit "Failed to start $SERVICE"
fi
log info "Compressing $TAR"
if ! nice -n "$NICE" xz -9 "$SCRATCH/$TAR"; then
error_exit "Failed to compress $SCRATCH/$TAR"
else
mv "$SCRATCH/$TAR.xz" "$BACKUP_DIR"
log info "Symlinking current archive"
ln -nfs "$BACKUP_DIR/$TAR.xz" "$BACKUP_DIR/minecraft-latest.tar.xz"
fi
log info "Backup complete"
}
main