diff --git a/rotate.sh b/rotate.sh index fc43250..2b6bfe8 100755 --- a/rotate.sh +++ b/rotate.sh @@ -1,131 +1,152 @@ #!/bin/bash ### # Stupid script to rotate a backup # # Author: Valerio B. # Date: Wed 4 Ago 2020 # License: CC 0 - public domain ## # do not proceed in case of errors set -e # current directory MYDIR="$(dirname "$(realpath "$0")")" # as default don't be quiet while rotating QUIET=0 # as default don't write in the log while rotating WRITELOG=0 +# +# Maximum time that your rotation could last +# +# Right now this should be a good default since it doesn't make much sense +# for a rotation to take more than this number of hours. +# +# If the script takes longer than this, the next rotation may not run. +# +# Note: at the moment this must be shorter than a single day. +# +# Current default: 6 hours (6 * 60 * 60 = 21600 seconds) +MAX_ROTATE_SECONDS=21600 + # include all the stuff and useful functions . "$MYDIR"/bootstrap.sh # arguments place="$1" days="$2" max="$3" # expected file containing last timestamp last_timestamp_file="$place.timestamp" # current timestamp current_timestamp=$(date +%s) # show usage function show_help_rotate() { echo "USAGE" echo " $0 PATH DAYS MAX_ROTATIONS" echo "EXAMPLE" echo " $0 /home/backups 1 30" } # all the arguments must exist (just check the last one) if [ -z "$max" ]; then echo "Bad usage" show_help_rotate exit 1 fi # the place to be rotated must exist if [ ! -e "$place" ]; then error "unexisting directory '$place'" exit 2 fi # validate max parameter if [ "$max" -lt 2 ]; then echo "The MAX parameter must be greater than 1" show_help_rotate exit 3 fi # check if the last timestamp was writed if [ -f "$last_timestamp_file" ]; then # check the timestamp saved in the file timestamp=$(<"$last_timestamp_file") if [ "$timestamp" -lt 1000 ]; then echo "bad format in file $last_timestamp_file" exit fi # seconds spent from the last rotation diff_seconds=$(expr "$current_timestamp" - "$timestamp") # expected seconds from the last rotation before continuing # NOTE: leave the star escaped to avoid syntax error in expr expected_seconds=$(expr "$days" "*" 86400) + # check if the duration in seconds is a day or more + if [ "$expected_seconds" -ge 86400 ]; then + + # the expected time since the last execution is never exactly the number of days in seconds + # Solution: remove few hours from the expected (just to say, uhm, 5 hours) + expected_seconds=$(expr "$expected_seconds" - "$MAX_ROTATE_SECONDS") + fi + # check if it's not passed enought time if [ "$diff_seconds" -lt "$expected_seconds" ]; then warn "Doing nothing: last rotation was executed $diff_seconds seconds ago (expected at least $expected_seconds)" exit fi fi # save the last timestamp before rotating everything # this will avoid even parallel rotations echo "$(date +%s)" > "$last_timestamp_file" # eventually drop the last backup step # if it does not exist, don't care max_path="$place.$max" drop "$max_path" # shift all the backups after="$max" while [[ "$after" -gt 1 ]]; do before=$(expr "$after" - 1) # do not process the root directory for no reason in the world if you type that by mistake # the --preserve-root is already implicit but... let's be sure! asd before_path="$place.$before" after_path="$place.$after" # the source must exist. asd if [ -e "$before_path" ]; then # the trailing slash means: copy files and not just the directory move "$before_path/" "$after_path" fi # next after="$before" done # at the end, move the base forward # the trailing slash means: copy files and not just the directory copy "$place/" "$place.1" # yeah! log "rotation concluded"