#!/usr/bin/env bash set -Eeuo pipefail umask 022 # STEP018B - SERVER ATTESO: 215.6 / ax-accessi # Audit esclusivo di /var/www/html/presenze.distribuite. # Cerca ricorsivamente copie locali reali di bower_components e node_modules, # senza toccare alcun altro portale custom. # Nessuna modifica. START_DIR="$PWD" STAMP="$(date '+%Y%m%d_%H%M%S')" BASE="STEP018B_2156_DISTRIBUITE_RECURSIVE_LOCAL_LIBRARIES_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}" SHARED_RELEASE="${STEP_SHARED_RELEASE:-/var/www/presenze-shared-libs/releases/presenze-legacy-20260723-v1}" 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 "Shared release: $SHARED_RELEASE" 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 readlink du stat basename numfmt; 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" [[ -d "$SHARED_RELEASE" ]] || fail "release condivisa assente: $SHARED_RELEASE" [[ -d "${SHARED_RELEASE}/bower_components" ]] || fail "shared bower_components assente" [[ -d "${SHARED_RELEASE}/node_modules" ]] || fail "shared node_modules assente" [[ "$FAILURES" -eq 0 ]] || exit 22 log "[1/4] Verifica symlink principali" printf 'libreria\tpath\ttipo\tlink_risolto\ttarget_atteso\tesito\n' \ >"${WORKDIR}/01_MAIN_LINKS.tsv" for lib in bower_components node_modules; do path="${TARGET_DIR}/${lib}" expected="${SHARED_RELEASE}/${lib}" if [[ ! -L "$path" ]]; then fail "${path} non รจ un symlink" printf '%s\t%s\t%s\t-\t%s\tERRORE\n' \ "$lib" "$path" "$(stat -c '%F' "$path" 2>/dev/null || printf 'assente')" "$expected" \ >>"${WORKDIR}/01_MAIN_LINKS.tsv" continue fi resolved="$(readlink -f "$path" 2>/dev/null || true)" status="OK" if [[ "$resolved" != "$expected" ]]; then status="TARGET_DIVERSO" fail "${path} punta a ${resolved}; atteso ${expected}" elif [[ ! -d "$resolved" ]]; then status="TARGET_ASSENTE" fail "destinazione condivisa assente: $resolved" fi printf '%s\t%s\tsymlink\t%s\t%s\t%s\n' \ "$lib" "$path" "$resolved" "$expected" "$status" \ >>"${WORKDIR}/01_MAIN_LINKS.tsv" done [[ "$FAILURES" -eq 0 ]] || exit 23 log "[2/4] Ricerca ricorsiva copie locali reali" printf 'percorso\tnome\ttipo\tbyte\tspazio\tazione_proposta\n' \ >"${WORKDIR}/02_RECURSIVE_CANDIDATES.tsv" REAL_DIRS=0 REAL_BYTES=0 OTHER_LINKS=0 while IFS= read -r -d '' item; do name="$(basename "$item")" if [[ "$item" == "${TARGET_DIR}/bower_components" || "$item" == "${TARGET_DIR}/node_modules" ]]; then continue fi if [[ -L "$item" ]]; then type="symlink" bytes=0 human="0B" action="NON_ELIMINARE_PRIMA_DI_VERIFICA" OTHER_LINKS=$((OTHER_LINKS + 1)) elif [[ -d "$item" ]]; then type="directory_reale" bytes="$(du -sb -- "$item" 2>/dev/null | awk '{print $1}' || printf '0')" human="$(numfmt --to=iec-i --suffix=B "$bytes" 2>/dev/null || printf '%sB' "$bytes")" action="CANDIDATA_RIMOZIONE" REAL_DIRS=$((REAL_DIRS + 1)) REAL_BYTES=$((REAL_BYTES + bytes)) else continue fi printf '%s\t%s\t%s\t%s\t%s\t%s\n' \ "$item" "$name" "$type" "$bytes" "$human" "$action" \ >>"${WORKDIR}/02_RECURSIVE_CANDIDATES.tsv" done < <( find "$TARGET_DIR" \ -xdev \ -mindepth 1 \ \( -type d -o -type l \) \ \( -name 'bower_components' -o -name 'node_modules' \ -o -name 'bower_components.*' -o -name 'node_modules.*' \ -o -name 'bower_components_*' -o -name 'node_modules_*' \) \ -print0 2>>"$LOGFILE" ) REAL_HUMAN="$(numfmt --to=iec-i --suffix=B "$REAL_BYTES" 2>/dev/null || printf '%sB' "$REAL_BYTES")" log "[3/4] Dimensione target senza seguire i symlink" TARGET_BYTES="$(du -sb -- "$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")" find "$TARGET_DIR" \ -xdev \ -mindepth 1 \ -maxdepth 2 \ -printf '%y\t%p\t%l\n' \ | sort >"${WORKDIR}/03_STRUCTURE_LEVEL_2.tsv" { printf 'voce\tvalore\n' printf 'target\t%s\n' "$TARGET_DIR" printf 'target_byte\t%s\n' "$TARGET_BYTES" printf 'target_spazio\t%s\n' "$TARGET_HUMAN" printf 'directory_reali_candidate\t%s\n' "$REAL_DIRS" printf 'spazio_recuperabile_byte\t%s\n' "$REAL_BYTES" printf 'spazio_recuperabile\t%s\n' "$REAL_HUMAN" printf 'altri_symlink_correlati\t%s\n' "$OTHER_LINKS" } >"${WORKDIR}/04_SUMMARY.tsv" log "[4/4] Esito" if [[ "$REAL_DIRS" -gt 0 ]]; then warn "trovate ${REAL_DIRS} copie locali reali candidate alla rimozione" fi if [[ "$OTHER_LINKS" -gt 0 ]]; then warn "trovati ${OTHER_LINKS} ulteriori symlink correlati da verificare" fi { echo "AUDIT COMPLETATO" echo "Errori: $FAILURES" echo "Avvisi: $WARNINGS" echo "Target esclusivo: $TARGET_DIR" echo "Symlink principali condivisi: OK" echo "Copie locali reali candidate: $REAL_DIRS" echo "Spazio potenzialmente recuperabile: $REAL_HUMAN" echo "Altri portali custom toccati: NO" echo "Nessuna modifica eseguita." } >"${WORKDIR}/99_SUMMARY.txt" report "Target esclusivo: $TARGET_DIR." report "Copie locali reali candidate: $REAL_DIRS." report "Spazio potenzialmente recuperabile: $REAL_HUMAN." report "Altri portali custom non toccati." log "AUDIT COMPLETATO: errori=${FAILURES}, avvisi=${WARNINGS}"