diff --git a/9.MediaVault/1.Install_MediaVault/excluded_patterns.txt b/9.MediaVault/1.Install_MediaVault/excluded_patterns.txt index fff68d16a7aa12a2be17a2a948b7359bbc854548..1edfb6d4e7d0a2ed78481a6d0f25b67bce48cb59 100644 --- a/9.MediaVault/1.Install_MediaVault/excluded_patterns.txt +++ b/9.MediaVault/1.Install_MediaVault/excluded_patterns.txt @@ -8,3 +8,5 @@ - apt-cacher-ng/ - *.lock - .nfs* +- *.m3u8 +- *.ts diff --git a/9.MediaVault/1.Install_MediaVault/rsync_tmbackup.sh b/9.MediaVault/1.Install_MediaVault/rsync_tmbackup.sh old mode 100755 new mode 100644 index 8a3cd6b60124860f83e41d1794267ec116e4e230..8b625b4f51e7a156e02e757ea17d550b5fbf9b0e --- a/9.MediaVault/1.Install_MediaVault/rsync_tmbackup.sh +++ b/9.MediaVault/1.Install_MediaVault/rsync_tmbackup.sh @@ -43,6 +43,11 @@ fn_display_usage() { echo " not be managed by the script - in particular they will not be" echo " automatically deleted." echo " Default: $LOG_DIR" + echo " --strategy Set the expiration strategy. Default: \"1:1 30:7 365:30\" means after one" + echo " day, keep one backup per day. After 30 days, keep one backup every 7 days." + echo " After 365 days keep one backup every 30 days." + echo " --no-auto-expire Disable automatically deleting backups when out of space. Instead an error" + echo " is logged, and the backup is aborted." echo "" echo "For more detailed help, please see the README file:" echo "" @@ -83,6 +88,56 @@ fn_expire_backup() { fn_rm_dir "$1" } +fn_expire_backups() { + local current_timestamp=$EPOCH + local last_kept_timestamp=9999999999 + + # Process each backup dir from most recent to oldest + for backup_dir in $(fn_find_backups | sort -r); do + local backup_date=$(basename "$backup_dir") + local backup_timestamp=$(fn_parse_date "$backup_date") + + # Skip if failed to parse date... + if [ -z "$backup_timestamp" ]; then + fn_log_warn "Could not parse date: $backup_dir" + continue + fi + + # Find which strategy token applies to this particular backup + for strategy_token in $(echo $EXPIRATION_STRATEGY | tr " " "\n" | sort -r -n); do + IFS=':' read -r -a t <<< "$strategy_token" + + # After which date (relative to today) this token applies (X) + local cut_off_timestamp=$((current_timestamp - ${t[0]} * 86400)) + + # Every how many days should a backup be kept past the cut off date (Y) + local cut_off_interval=$((${t[1]} * 86400)) + + # If we've found the strategy token that applies to this backup + if [ "$backup_timestamp" -le "$cut_off_timestamp" ]; then + + # Special case: if Y is "0" we delete every time + if [ $cut_off_interval -eq "0" ]; then + fn_expire_backup "$backup_dir" + break + fi + + # Check if the current backup is in the interval between + # the last backup that was kept and Y + local interval_since_last_kept=$((last_kept_timestamp - backup_timestamp)) + if [ "$interval_since_last_kept" -lt "$cut_off_interval" ]; then + # Yes: Delete that one + fn_expire_backup "$backup_dir" + else + # No: Keep it + last_kept_timestamp=$backup_timestamp + fi + break + fi + done + done +} + fn_parse_ssh() { # To keep compatibility with bash version < 3, we use grep if echo "$DEST_FOLDER"|grep -Eq '^[A-Za-z0-9\._%\+\-]+@[A-Za-z0-9.\-]+\:.+$' @@ -157,6 +212,8 @@ DEST_FOLDER="" EXCLUSION_FILE="" LOG_DIR="$HOME/.$APPNAME" AUTO_DELETE_LOG="1" +EXPIRATION_STRATEGY="1:1 30:7 365:30" +AUTO_EXPIRE="1" RSYNC_FLAGS="-D --numeric-ids --links --hard-links --one-file-system --itemize-changes --times --recursive --perms --owner --group --stats --human-readable --timeout 30" @@ -179,11 +236,18 @@ while :; do shift RSYNC_FLAGS="$1" ;; + --strategy) + shift + EXPIRATION_STRATEGY="$1" + ;; --log-dir) shift LOG_DIR="$1" AUTO_DELETE_LOG="0" ;; + --no-auto-expire) + AUTO_EXPIRE="0" + ;; --) shift SRC_FOLDER="$1" @@ -359,30 +423,7 @@ while : ; do # Purge certain old backups before beginning new backup. # ----------------------------------------------------------------------------- - # Default value for $PREV ensures that the most recent backup is never deleted. - PREV="0000-00-00-000000" - for FILENAME in $(fn_find_backups | sort -r); do - BACKUP_DATE=$(basename "$FILENAME") - TIMESTAMP=$(fn_parse_date $BACKUP_DATE) - - # Skip if failed to parse date... - if [ -z "$TIMESTAMP" ]; then - fn_log_warn "Could not parse date: $FILENAME" - continue - fi - - if [ $TIMESTAMP -ge $KEEP_ALL_DATE ]; then - true - elif [ $TIMESTAMP -ge $KEEP_DAILIES_DATE ]; then - # Delete all but the most recent of each day. - [ "${BACKUP_DATE:0:10}" == "${PREV:0:10}" ] && fn_expire_backup "$FILENAME" - else - # Delete all but the most recent of each month. - [ "${BACKUP_DATE:0:7}" == "${PREV:0:7}" ] && fn_expire_backup "$FILENAME" - fi - - PREV=$BACKUP_DATE - done + fn_expire_backups # ----------------------------------------------------------------------------- # Start backup @@ -420,6 +461,12 @@ while : ; do NO_SPACE_LEFT="$(grep "No space left on device (28)\|Result too large (34)" "$LOG_FILE")" if [ -n "$NO_SPACE_LEFT" ]; then + + if [[ $AUTO_EXPIRE == "0" ]]; then + fn_log_error "No space left on device, and automatic purging of old backups is disabled." + exit 1 + fi + fn_log_warn "No space left on device - removing oldest backup and resuming." if [[ "$(fn_find_backups | wc -l)" -lt "2" ]]; then @@ -461,3 +508,4 @@ while : ; do exit $EXIT_CODE done +