#!/bin/bash -eu ### Copyright 1999-2025. WebPros International GmbH. All rights reserved. # Removes temporary backups older than MAX_AGE days made by deployer_lib MAX_AGE=90 # days FAIL2BAN_DIR='/etc/fail2ban' MODSEC_DIR_APACHE='/etc/apache2/modsecurity.d/rules' MODSEC_DIR_NGINX='/etc/nginx/modsecurity.d/rules' REMOVAL_PATTERN='*.saved-*-*' TIMESTAMP_PATTERN_SED='s/.\+\.saved-\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)T\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)-.\+$/\1-\2-\3T\4:\5:\6/' logerror() { IFS=' ' echo "ERROR: $*" >&2 } logdebug() { if [ -n "$DEBUG_MODE" ]; then IFS=' ' echo "DEBUG: $*" >&2 fi } die() { logerror "$@" exit 1 } # path_in ... # Returns true if the path is in one of the directories. function path_in() { local path=$1 shift local dir for dir in "$@"; do if [ "${path#$dir}" != "$path" ]; then return 0 fi done return 1 } function rm_path() { local path=$1 if ! path_in "$path" "${DIRS[@]}"; then die "Path '$path' is out of a permitted directory" fi if [ "${path%$REMOVAL_PATTERN}" = "$path" ]; then die "Path '$path' doesn't match the removal pattern" fi logdebug "Removing '$path'" $DRY_RUN rm -rf "$path" } function main() { local now=$(date +%s) local min_timestamp=$((now - MAX_AGE * 24 * 60 * 60)) logdebug "Removing temporary backups older than $(date --date="@$min_timestamp" --iso-8601=seconds) ($min_timestamp)" while IFS= read -r -d $'\0' path; do local timestamp_iso=$(sed "$TIMESTAMP_PATTERN_SED" <<<"$path") local timestamp_unix timestamp_unix=$(date --date="$timestamp_iso" +%s) || { logerror "The path '$path' doesn't have a valid timestamp, skipping" && continue; } logdebug "Examining '$path' with timestamp $timestamp_iso ($timestamp_unix)" if [ "$timestamp_unix" -lt "$min_timestamp" ]; then rm_path "$path" fi done < <(find "${DIRS[@]}" -name "$REMOVAL_PATTERN" -print0) } DEBUG_MODE="" DRY_RUN="" while [ $# -gt 0 ]; do case "$1" in -h|--help) cat <<-EOT Usage: $0 [] Removes old temporary backups made by deployer_lib. Options: --debug Turn on debug mode. --dry-run Don't actually remove anything, just show commands to be performed. --max-age MAX_AGE Remove temporary backups older than MAX_AGE days (default: $MAX_AGE). EOT exit 0 ;; --debug) DEBUG_MODE=1 shift 1 ;; --dry-run) DRY_RUN="echo" shift 1 ;; --max-age) MAX_AGE=$2 shift 2 ;; *) die "Unrecognized argument: $1" ;; esac done DIRS=() dir="" for dir in "$FAIL2BAN_DIR" "$MODSEC_DIR_APACHE" "$MODSEC_DIR_NGINX"; do if [ -n "$dir" -a -d "$dir" ]; then DIRS+=("$dir") fi done main