Files
bash/scripts/log_rotate_archive.sh
T

98 lines
2.5 KiB
Bash

#!/usr/bin/env bash
#
# Archive old log files into compressed tarballs.
#
# This script is useful when logrotate is unavailable or when application logs
# need custom archival handling. It does not delete active logs by default.
#
# Usage:
# bash log_rotate_archive.sh --source /var/log/myapp --archive /backup/logs
# bash log_rotate_archive.sh --source ./logs --archive ./archives --older-than-days 3 --delete-originals
#
# Options:
# --source DIR Directory containing log files.
# --archive DIR Directory where archives will be stored.
# --older-than-days N Archive files older than N days. Default: 7.
# --delete-originals Delete original files after a successful archive.
# --help Show this help message.
set -Eeuo pipefail
source_dir=""
archive_dir=""
older_than_days="7"
delete_originals=false
usage() {
sed -n '2,21p' "$0" | sed 's/^# \{0,1\}//'
}
log() {
printf '[%s] %s\n' "$(date -Is)" "$*"
}
while [[ "$#" -gt 0 ]]; do
case "$1" in
--source)
source_dir="${2:-}"
shift 2
;;
--archive)
archive_dir="${2:-}"
shift 2
;;
--older-than-days)
older_than_days="${2:-}"
[[ "$older_than_days" =~ ^[0-9]+$ ]] || { printf 'ERROR: --older-than-days must be an integer.\n' >&2; exit 1; }
shift 2
;;
--delete-originals)
delete_originals=true
shift
;;
--help|-h)
usage
exit 0
;;
*)
printf 'ERROR: unknown option: %s\n' "$1" >&2
usage >&2
exit 1
;;
esac
done
[[ -d "$source_dir" ]] || { printf 'ERROR: source directory does not exist: %s\n' "$source_dir" >&2; exit 1; }
[[ -n "$archive_dir" ]] || { printf 'ERROR: --archive is required.\n' >&2; exit 1; }
mkdir -p "$archive_dir"
timestamp="$(date +%Y%m%d-%H%M%S)"
manifest="$(mktemp)"
archive_file="${archive_dir}/logs-${timestamp}.tar.gz"
find "$source_dir" -type f -name '*.log' -mtime "+${older_than_days}" -print > "$manifest"
if [[ ! -s "$manifest" ]]; then
log "No log files older than ${older_than_days} days were found."
rm -f "$manifest"
exit 0
fi
log "Creating archive: ${archive_file}"
tar -czf "$archive_file" --files-from "$manifest"
if [[ ! -s "$archive_file" ]]; then
printf 'ERROR: archive was not created or is empty: %s\n' "$archive_file" >&2
rm -f "$manifest"
exit 1
fi
if [[ "$delete_originals" == true ]]; then
log "Deleting archived original files."
xargs -r rm -f < "$manifest"
fi
rm -f "$manifest"
log "Log archive completed successfully."