From e1597c3ca7e1a11a0535e87753fcccc4a566675a Mon Sep 17 00:00:00 2001 From: Paulo Nonato Date: Sat, 18 Apr 2026 23:31:21 -0300 Subject: [PATCH] Add scripts/log_rotate_archive.sh --- scripts/log_rotate_archive.sh | 97 +++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 scripts/log_rotate_archive.sh diff --git a/scripts/log_rotate_archive.sh b/scripts/log_rotate_archive.sh new file mode 100644 index 0000000..9373a72 --- /dev/null +++ b/scripts/log_rotate_archive.sh @@ -0,0 +1,97 @@ +#!/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." +