diff --git a/README.md b/README.md index 26e9789..938b135 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,14 @@ or Backup the Minecraft world. Backup all worlds by default. +* list-backups [world] + + List the datetime of the backups for the world. + +* restore-backup [world] [datetime] + + Restore a backup for a world that was taken at the datetime. + * console [world] Connect to the Minecraft world server's console. Hit [Ctrl-D] to detach. diff --git a/minecraft_server b/minecraft_server index 859cfaf..53972b6 100755 --- a/minecraft_server +++ b/minecraft_server @@ -116,6 +116,12 @@ Options: backup Backup the Minecraft world. Backup all worlds by default. + list-backups + List the datetime of the backups for the world. + + restore-backup + Restore a backup for a world that was taken at the datetime. + map Run the Minecraft Overviewer mapping software on the Minecraft world. Map all worlds by default. @@ -1216,12 +1222,48 @@ worldBackup() { execute "mkdir -p $BACKUP_LOCATION" $USER_NAME # Create the backup. execute "$RDIFF_BACKUP -v5 --print-statistics $WORLDS_LOCATION/$1 $BACKUP_LOCATION/$1 >> $BACKUP_LOG" $USER_NAME + # Set the permissions for the backup location. + execute "chmod a+rX -R $BACKUP_LOCATION" $USER_NAME # Cleanup old backups. if [ $BACKUP_DURATION -gt 0 ]; then execute "$RDIFF_BACKUP --remove-older-than ${BACKUP_DURATION}D --force $BACKUP_LOCATION/$1 >> $BACKUP_LOG" $USER_NAME fi } +# --------------------------------------------------------------------------- +# List the backups for the world server. +# +# @param 1 The world server of interest. +# --------------------------------------------------------------------------- +worldBackupList() { + if [ -d $BACKUP_LOCATION/$1 ]; then + # Grab the list of backups for the world server. + $RDIFF_BACKUP -l $BACKUP_LOCATION/$1 | + $PERL -e ' + foreach (reverse <>) { + # Search for a datetime format YYYY-MM-DDThh:mm:ssTZD. + # Datetime specification: http://www.w3.org/TR/NOTE-datetime + if ($_ =~ /(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2})/) { + print "$1\n"; + } + } + ' + fi +} + +# --------------------------------------------------------------------------- +# Restore a backup for the world server. +# +# @param 1 The world server of interest. +# @param 2 The datetime of the backup to restore. +# --------------------------------------------------------------------------- +worldBackupRestore() { + if [ -d $BACKUP_LOCATION/$1 ]; then + worldBackup "$1" + execute "$RDIFF_BACKUP -r $2 $BACKUP_LOCATION/$1 $WORLDS_LOCATION/$1" $USER_NAME + fi +} + # --------------------------------------------------------------------------- # Update the Minecraft client software. # @@ -2088,6 +2130,32 @@ case "$1" in done printf ".\n" ;; + list-backups) + if [ -n "$2" ] && [ $(listContains "$2" "$(getEnabledWorlds)") -eq 1 ]; then + worldBackupList "$2" + elif [ -n "$2" ]; then + printf "World '$2' not recognized.\n" + printf " Usage: $0 $1 \n" + exit 1 + else + printf "World not supplied.\n" + printf " Usage: $0 $1 \n" + exit 1 + fi + ;; + restore-backup) + if [ -n "$2" ] && [ $(listContains "$2" "$(getEnabledWorlds)") -eq 1 ]; then + worldBackupRestore "$2" "$3" + elif [ -n "$2" ]; then + printf "World '$2' not recognized.\n" + printf " Usage: $0 $1 \n" + exit 1 + else + printf "World not supplied.\n" + printf " Usage: $0 $1 \n" + exit 1 + fi + ;; update) checkPermission # Figure out which worlds to update. diff --git a/mscs_completion b/mscs_completion index 4ada4b9..5c58bef 100644 --- a/mscs_completion +++ b/mscs_completion @@ -1,42 +1,51 @@ MINECRAFT_SERVER=/etc/init.d/minecraft_server _minecraft_server() { - local CUR PREV OPTS WORLDS + local OPTS WORLDS COMPREPLY=() - CUR=${COMP_WORDS[COMP_CWORD]} - PREV=${COMP_WORDS[COMP_CWORD-1]} + + COMP_WORDBREAKS=${COMP_WORDBREAKS//:} OPTS=" backup console create delete disable enable force-restart force-stop list - logrotate map new overviewer remove restart send show start status - stop sync update watch + list-backups logrotate map new overviewer remove restart restore-backup + send show start status stop sync update watch " LIST_OPTS="enabled disabled running stopped" if [ $COMP_CWORD -eq 1 ]; then - COMPREPLY=($(compgen -W "$OPTS" -- $CUR)) - else - case $PREV in + COMPREPLY=($(compgen -W "$OPTS" -- ${COMP_WORDS[COMP_CWORD]})) + elif [ $COMP_CWORD -eq 2 ]; then + case ${COMP_WORDS[COMP_CWORD-1]} in start) WORLDS=$($MINECRAFT_SERVER list stopped) - COMPREPLY=($(compgen -W "$WORLDS" -- $CUR)) + COMPREPLY=($(compgen -W "$WORLDS" -- ${COMP_WORDS[COMP_CWORD]})) ;; stop|force-stop|restart|force-restart|send|console) WORLDS=$($MINECRAFT_SERVER list running) - COMPREPLY=($(compgen -W "$WORLDS" -- $CUR)) + COMPREPLY=($(compgen -W "$WORLDS" -- ${COMP_WORDS[COMP_CWORD]})) ;; delete|remove|disable|status|show|sync|send|watch|logrotate| \ - backup|map|overviewer) + backup|map|overviewer|list-backups|restore-backup) WORLDS=$($MINECRAFT_SERVER list enabled) - COMPREPLY=($(compgen -W "$WORLDS" -- $CUR)) + COMPREPLY=($(compgen -W "$WORLDS" -- ${COMP_WORDS[COMP_CWORD]})) ;; enable) WORLDS=$($MINECRAFT_SERVER list disabled) - COMPREPLY=($(compgen -W "$WORLDS" -- $CUR)) + COMPREPLY=($(compgen -W "$WORLDS" -- ${COMP_WORDS[COMP_CWORD]})) ;; ls|list) - COMPREPLY=($(compgen -W "$LIST_OPTS" -- $CUR)) + COMPREPLY=($(compgen -W "$LIST_OPTS" -- ${COMP_WORDS[COMP_CWORD]})) + ;; + *) + ;; + esac + elif [ $COMP_CWORD -eq 3 ]; then + case ${COMP_WORDS[COMP_CWORD-2]} in + restore-backup) + BACKUPS=$($MINECRAFT_SERVER list-backups "${COMP_WORDS[COMP_CWORD-1]}") + COMPREPLY=($(compgen -W "$BACKUPS" -- "${COMP_WORDS[COMP_CWORD]}")) ;; *) ;;