#!/usr/bin/env bash set -Eeuo pipefail umask 022 # STEP019 - SERVER ATTESO: 215.6 / ax-accessi # Analizza esclusivamente lo spazio residuo di: # /var/www/html/presenze.distribuite # # Non segue i symlink bower_components/node_modules e non tocca altri portali. # Produce: # - dimensioni delle directory di primo livello; # - dimensioni delle sottodirectory di libs, documents, assets e components; # - elenco dei file più grandi; # - riepilogo delle aree che occupano più spazio. # # Nessuna modifica. START_DIR="$PWD" STAMP="$(date '+%Y%m%d_%H%M%S')" BASE="STEP019_2156_DISTRIBUITE_REMAINING_SPACE_BREAKDOWN_AUDIT_ONLY_${STAMP}" WORKDIR="${START_DIR}/.${BASE}_work_$$" OUTZIP="${START_DIR}/${BASE}.zip" LOGFILE="${WORKDIR}/run.log" REPORT="${WORKDIR}/report.txt" PACKAGED=0 FAILURES=0 WARNINGS=0 EXPECTED_HOST="${STEP_EXPECTED_HOST:-ax-accessi}" EXPECTED_IP="${STEP_EXPECTED_IP:-192.168.215.6}" SKIP_SERVER_CHECK="${STEP_SKIP_SERVER_CHECK:-0}" TARGET_DIR="${STEP_TARGET_DIR:-/var/www/html/presenze.distribuite}" mkdir -p "$WORKDIR" : >"$LOGFILE" : >"$REPORT" log() { printf '%s\n' "$*" | tee -a "$LOGFILE"; } report() { printf '%s\n' "$*" >>"$REPORT"; } fail() { FAILURES=$((FAILURES + 1)); log "ERRORE: $*"; report "ERRORE: $*"; } warn() { WARNINGS=$((WARNINGS + 1)); log "ATTENZIONE: $*"; report "ATTENZIONE: $*"; } package_results() { local rc="${1:-0}" local zip_rc=0 [[ "$PACKAGED" -eq 1 ]] && return 0 PACKAGED=1 report "" report "Esito finale: errori=${FAILURES}, avvisi=${WARNINGS}, exit_code=${rc}" rm -f -- "$OUTZIP" if ! command -v zip >/dev/null 2>&1; then rm -rf -- "$WORKDIR" printf '%s\n' "ERRORE: comando zip non disponibile" >&2 return 127 fi (cd "$WORKDIR" && zip -qr "$OUTZIP" .) || zip_rc=$? if [[ "$zip_rc" -eq 0 ]]; then zip -T "$OUTZIP" >>"$LOGFILE" 2>&1 || zip_rc=$? fi rm -rf -- "$WORKDIR" if [[ "$zip_rc" -ne 0 ]]; then rm -f -- "$OUTZIP" printf '%s\n' "ERRORE: creazione/verifica ZIP fallita (rc=${zip_rc})" >&2 return "$zip_rc" fi printf '%s\n' "ZIP CREATO E VERIFICATO: $OUTZIP" } on_exit() { local rc=$? trap - EXIT INT TERM HUP package_results "$rc" || rc=$? exit "$rc" } trap on_exit EXIT trap 'exit 130' INT trap 'exit 143' TERM HUP log "$BASE" log "SERVER ATTESO: 215.6 / ax-accessi" log "TARGET ESCLUSIVO: $TARGET_DIR" log "ALTRI PORTALI CUSTOM: NON TOCCATI" log "MODALITA': AUDIT ONLY - NESSUNA MODIFICA" log "Avvio: $(date --iso-8601=seconds)" ACTUAL_HOST="$(hostname -s 2>/dev/null || hostname)" ACTUAL_IPS="$(hostname -I 2>/dev/null | xargs || true)" { echo "STEP: $BASE" echo "Server atteso: 215.6 / ax-accessi" echo "Target esclusivo: $TARGET_DIR" echo "Altri portali custom: NON TOCCATI" echo "Modalita': AUDIT ONLY" echo "Data: $(date --iso-8601=seconds)" echo "Hostname: $ACTUAL_HOST" echo "IP: $ACTUAL_IPS" echo } >>"$REPORT" for cmd in grep awk wc sort zip hostname xargs tr find du numfmt basename head; do command -v "$cmd" >/dev/null 2>&1 || fail "comando richiesto non disponibile: $cmd" done [[ "$FAILURES" -eq 0 ]] || exit 20 if [[ "$SKIP_SERVER_CHECK" != "1" ]]; then [[ "$ACTUAL_HOST" == "$EXPECTED_HOST" ]] \ || fail "hostname ${ACTUAL_HOST}; previsto ${EXPECTED_HOST}" if [[ -n "$EXPECTED_IP" ]] && ! grep -qw -- "$EXPECTED_IP" <<<"$ACTUAL_IPS"; then fail "IP ${EXPECTED_IP} non presente tra: ${ACTUAL_IPS}" fi fi [[ "$FAILURES" -eq 0 ]] || exit 21 [[ "$TARGET_DIR" == "/var/www/html/presenze.distribuite" ]] \ || fail "target inatteso: $TARGET_DIR" [[ -d "$TARGET_DIR" ]] || fail "cartella target assente: $TARGET_DIR" [[ "$FAILURES" -eq 0 ]] || exit 22 log "[1/5] Dimensione totale reale senza seguire i symlink" TARGET_BYTES="$(du -sbx -- "$TARGET_DIR" 2>/dev/null | awk '{print $1}' || printf '0')" TARGET_HUMAN="$(numfmt --to=iec-i --suffix=B "$TARGET_BYTES" 2>/dev/null || printf '%sB' "$TARGET_BYTES")" printf 'voce\tbyte\tspazio\n' >"${WORKDIR}/01_TOTAL_SIZE.tsv" printf 'presenze.distribuite\t%s\t%s\n' "$TARGET_BYTES" "$TARGET_HUMAN" \ >>"${WORKDIR}/01_TOTAL_SIZE.tsv" log "[2/5] Directory di primo livello" printf 'byte\tspazio\tpercorso\n' >"${WORKDIR}/02_TOP_LEVEL_DIRECTORIES.tsv" while IFS= read -r -d '' dir; do if [[ -L "$dir" ]]; then continue fi bytes="$(du -sbx -- "$dir" 2>/dev/null | awk '{print $1}' || printf '0')" human="$(numfmt --to=iec-i --suffix=B "$bytes" 2>/dev/null || printf '%sB' "$bytes")" printf '%s\t%s\t%s\n' "$bytes" "$human" "$dir" done < <( find "$TARGET_DIR" \ -xdev \ -mindepth 1 \ -maxdepth 1 \ -type d \ -print0 2>>"$LOGFILE" ) | sort -rn -k1,1 >>"${WORKDIR}/02_TOP_LEVEL_DIRECTORIES.tsv" log "[3/5] Sottodirectory principali" printf 'area\tbyte\tspazio\tpercorso\n' >"${WORKDIR}/03_MAJOR_SUBDIRECTORIES.tsv" for area in libs documents assets components external_data docs; do root="${TARGET_DIR}/${area}" [[ -d "$root" && ! -L "$root" ]] || continue while IFS= read -r -d '' dir; do [[ -L "$dir" ]] && continue bytes="$(du -sbx -- "$dir" 2>/dev/null | awk '{print $1}' || printf '0')" human="$(numfmt --to=iec-i --suffix=B "$bytes" 2>/dev/null || printf '%sB' "$bytes")" printf '%s\t%s\t%s\t%s\n' "$area" "$bytes" "$human" "$dir" done < <( find "$root" \ -xdev \ -mindepth 1 \ -maxdepth 1 \ -type d \ -print0 2>>"$LOGFILE" ) done | sort -t $'\t' -rn -k2,2 >>"${WORKDIR}/03_MAJOR_SUBDIRECTORIES.tsv" log "[4/5] File più grandi" printf 'byte\tspazio\tpercorso\n' >"${WORKDIR}/04_LARGEST_FILES.tsv" find "$TARGET_DIR" \ -xdev \ -type f \ -printf '%s\t%p\n' 2>>"$LOGFILE" \ | sort -rn -k1,1 \ | head -n 200 \ | while IFS=$'\t' read -r bytes path; do human="$(numfmt --to=iec-i --suffix=B "$bytes" 2>/dev/null || printf '%sB' "$bytes")" printf '%s\t%s\t%s\n' "$bytes" "$human" "$path" done >>"${WORKDIR}/04_LARGEST_FILES.tsv" FILES_OVER_10M="$(find "$TARGET_DIR" -xdev -type f -size +10M -print 2>>"$LOGFILE" | wc -l | tr -d ' ')" FILES_OVER_50M="$(find "$TARGET_DIR" -xdev -type f -size +50M -print 2>>"$LOGFILE" | wc -l | tr -d ' ')" TOP_DIR_LINE="$(awk -F '\t' 'NR==2 {print $1"\t"$2"\t"$3}' "${WORKDIR}/02_TOP_LEVEL_DIRECTORIES.tsv")" TOP_DIR_BYTES="$(printf '%s' "$TOP_DIR_LINE" | cut -f1)" TOP_DIR_HUMAN="$(printf '%s' "$TOP_DIR_LINE" | cut -f2)" TOP_DIR_PATH="$(printf '%s' "$TOP_DIR_LINE" | cut -f3)" log "[5/5] Esito" { printf 'voce\tvalore\n' printf 'target_spazio\t%s\n' "$TARGET_HUMAN" printf 'file_oltre_10MiB\t%s\n' "$FILES_OVER_10M" printf 'file_oltre_50MiB\t%s\n' "$FILES_OVER_50M" printf 'directory_piu_grande\t%s\n' "$TOP_DIR_PATH" printf 'directory_piu_grande_spazio\t%s\n' "$TOP_DIR_HUMAN" printf 'directory_piu_grande_byte\t%s\n' "$TOP_DIR_BYTES" } >"${WORKDIR}/05_SUMMARY.tsv" { echo "AUDIT COMPLETATO" echo "Errori: $FAILURES" echo "Avvisi: $WARNINGS" echo "Target esclusivo: $TARGET_DIR" echo "Spazio residuo reale: $TARGET_HUMAN" echo "Directory più grande: $TOP_DIR_PATH ($TOP_DIR_HUMAN)" echo "File oltre 10 MiB: $FILES_OVER_10M" echo "File oltre 50 MiB: $FILES_OVER_50M" echo "bower_components/node_modules condivisi: non conteggiati" echo "Altri portali custom toccati: NO" echo "Nessuna modifica eseguita." } >"${WORKDIR}/99_SUMMARY.txt" report "Spazio residuo reale: $TARGET_HUMAN." report "Directory più grande: $TOP_DIR_PATH ($TOP_DIR_HUMAN)." report "File oltre 10 MiB: $FILES_OVER_10M." report "Altri portali custom non toccati." log "AUDIT COMPLETATO: errori=${FAILURES}, avvisi=${WARNINGS}"