#!/usr/bin/env bash set -Eeuo pipefail umask 022 # STEP027 - SERVER ATTESO: 215.6 / ax-accessi # # Audit esclusivo di /var/www/html/presenze.distribuite. # # Analizza le aree più probabili da rimuovere dalla distribuzione base: # - documents # - external_data # - docs # - upd-page-html # - components/templates/custom_templates/tmpwip # - test # # Per ogni area: # - misura lo spazio; # - elenca le sottodirectory principali; # - cerca riferimenti esterni nel codice; # - elenca i file più grandi. # # Confronta inoltre tmpwip/ax_mensa con ax_mensa per quantificare i file # identici duplicati. # # Nessuna modifica. # Nessun altro portale custom toccato. START_DIR="$PWD" STAMP="$(date '+%Y%m%d_%H%M%S')" BASE="STEP027_2156_DISTRIBUITE_LARGE_REMOVABLE_AREAS_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}" CANDIDATES=( "documents" "external_data" "docs" "upd-page-html" "components/templates/custom_templates/tmpwip" "test" ) TMPWIP_MENSA_REL="components/templates/custom_templates/tmpwip/ax_mensa" CANONICAL_MENSA_REL="components/templates/custom_templates/ax_mensa" 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 dirname stat sha256sum cut sed comm; 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 [[ "$TARGET_DIR" == "/var/www/html/presenze.distribuite" ]] \ || fail "target inatteso: $TARGET_DIR" [[ -d "$TARGET_DIR" ]] || fail "target assente: $TARGET_DIR" [[ ! -L "$TARGET_DIR" ]] || fail "target root non deve essere symlink" [[ "$FAILURES" -eq 0 ]] || exit 21 log "[1/6] Dimensioni delle aree candidate" printf 'area\tesiste\ttipo\tbyte\tspazio\tfile\tdirectory\n' \ >"${WORKDIR}/01_CANDIDATE_SIZES.tsv" TOTAL_BYTES=0 EXISTING_COUNT=0 for rel in "${CANDIDATES[@]}"; do path="${TARGET_DIR}/${rel}" [[ "$path" == "${TARGET_DIR}/"* ]] || { fail "candidato fuori target: $path" continue } if [[ -L "$path" ]]; then exists="SI" type="symlink" bytes=0 human="0B" files=0 dirs=0 warn "area candidata è un symlink e non sarà considerata rimovibile: $path" elif [[ -d "$path" ]]; then exists="SI" type="directory" bytes="$(du -sbx -- "$path" 2>/dev/null | awk '{print $1}' || printf '0')" human="$(numfmt --to=iec-i --suffix=B "$bytes" 2>/dev/null || printf '%sB' "$bytes")" files="$(find "$path" -xdev -type f | wc -l | tr -d ' ')" dirs="$(find "$path" -xdev -type d | wc -l | tr -d ' ')" TOTAL_BYTES=$((TOTAL_BYTES + bytes)) EXISTING_COUNT=$((EXISTING_COUNT + 1)) else exists="NO" type="assente" bytes=0 human="0B" files=0 dirs=0 fi printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \ "$rel" "$exists" "$type" "$bytes" "$human" "$files" "$dirs" \ >>"${WORKDIR}/01_CANDIDATE_SIZES.tsv" done TOTAL_HUMAN="$(numfmt --to=iec-i --suffix=B "$TOTAL_BYTES" 2>/dev/null || printf '%sB' "$TOTAL_BYTES")" log "[2/6] Sottodirectory principali" SUBDIR_RAW="${WORKDIR}/.subdirs_raw.tsv" : >"$SUBDIR_RAW" for rel in "${CANDIDATES[@]}"; do root="${TARGET_DIR}/${rel}" [[ -d "$root" && ! -L "$root" ]] || continue while IFS= read -r -d '' dir; do 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' \ "$bytes" "$human" "$rel" "$dir" \ >>"$SUBDIR_RAW" done < <( find "$root" \ -xdev \ -mindepth 1 \ -maxdepth 2 \ -type d \ -print0 2>>"$LOGFILE" ) done { printf 'byte\tspazio\tarea\tpercorso\n' sort -t $'\t' -rn -k1,1 "$SUBDIR_RAW" } >"${WORKDIR}/02_SUBDIRECTORIES.tsv" log "[3/6] Preparazione elenco codice esterno alle aree candidate" CODE_FILES="${WORKDIR}/03_CODE_FILES.list" : >"$CODE_FILES" find "$TARGET_DIR" \ -xdev \ \( \ -path "${TARGET_DIR}/bower_components" \ -o -path "${TARGET_DIR}/node_modules" \ -o -path "${TARGET_DIR}/documents" \ -o -path "${TARGET_DIR}/external_data" \ -o -path "${TARGET_DIR}/docs" \ -o -path "${TARGET_DIR}/upd-page-html" \ -o -path "${TARGET_DIR}/components/templates/custom_templates/tmpwip" \ -o -path "${TARGET_DIR}/test" \ -o -path "${TARGET_DIR}/libs/stimulsoft_legacy" \ \) -prune \ -o -type f \ \( \ -name '*.php' \ -o -name '*.js' \ -o -name '*.json' \ -o -name '*.html' \ -o -name '*.htm' \ -o -name '*.css' \ -o -name '*.scss' \ -o -name '*.less' \ -o -name '*.xml' \ -o -name '*.ini' \ -o -name '*.conf' \ -o -name '*.tpl' \ -o -name '*.mrt' \ -o -name '*.txt' \ \) \ -print0 >"$CODE_FILES" CODE_FILE_COUNT="$(tr -cd '\0' <"$CODE_FILES" | wc -c | tr -d ' ')" log "[4/6] Riferimenti esterni alle aree candidate" REFERENCES="${WORKDIR}/04_EXTERNAL_REFERENCES.tsv" printf 'area\tfile\triga\ttesto\n' >"$REFERENCES" scan_pattern() { local area="$1" local pattern="$2" local file local match local lineno local content local clean while IFS= read -r -d '' file; do while IFS= read -r match; do [[ -n "$match" ]] || continue lineno="${match%%:*}" content="${match#*:}" clean="$(printf '%s' "$content" | tr '\t\r\n' ' ' | cut -c1-500)" printf '%s\t%s\t%s\t%s\n' \ "$area" "$file" "$lineno" "$clean" \ >>"$REFERENCES" done < <(grep -nI -E "$pattern" "$file" 2>/dev/null || true) done <"$CODE_FILES" } scan_pattern "documents" '(^|[^[:alnum:]_])documents(/|["'\''])' scan_pattern "external_data" 'external_data' scan_pattern "docs" '(^|[^[:alnum:]_])docs(/|["'\''])' scan_pattern "upd-page-html" 'upd-page-html' scan_pattern "tmpwip" 'tmpwip' scan_pattern "test" '(^|[^[:alnum:]_])test(/|["'\''])' printf 'area\triferimenti\tfile_distinti\n' \ >"${WORKDIR}/05_REFERENCE_SUMMARY.tsv" for area in documents external_data docs upd-page-html tmpwip test; do refs="$(awk -F '\t' -v a="$area" 'NR>1 && $1==a {n++} END {print n+0}' "$REFERENCES")" files="$(awk -F '\t' -v a="$area" 'NR>1 && $1==a {print $2}' "$REFERENCES" | sort -u | wc -l | tr -d ' ')" printf '%s\t%s\t%s\n' "$area" "$refs" "$files" \ >>"${WORKDIR}/05_REFERENCE_SUMMARY.tsv" done log "[5/6] Duplicazione tmpwip/ax_mensa rispetto ad ax_mensa" TMPWIP="${TARGET_DIR}/${TMPWIP_MENSA_REL}" CANONICAL="${TARGET_DIR}/${CANONICAL_MENSA_REL}" printf 'voce\tvalore\n' >"${WORKDIR}/06_TMPWIP_DUPLICATION.tsv" if [[ -d "$TMPWIP" && ! -L "$TMPWIP" && -d "$CANONICAL" && ! -L "$CANONICAL" ]]; then TMP_HASHES="${WORKDIR}/.tmpwip_hashes.tsv" CANON_HASHES="${WORKDIR}/.canonical_hashes.tsv" TMP_HASH_ONLY="${WORKDIR}/.tmpwip_hash_only.txt" CANON_HASH_ONLY="${WORKDIR}/.canonical_hash_only.txt" COMMON_HASHES="${WORKDIR}/.common_hashes.txt" : >"$TMP_HASHES" : >"$CANON_HASHES" while IFS= read -r -d '' file; do hash="$(sha256sum "$file" | awk '{print $1}')" bytes="$(stat -c '%s' "$file")" rel="${file#${TMPWIP}/}" printf '%s\t%s\t%s\n' "$hash" "$bytes" "$rel" >>"$TMP_HASHES" done < <(find "$TMPWIP" -xdev -type f -print0) while IFS= read -r -d '' file; do hash="$(sha256sum "$file" | awk '{print $1}')" bytes="$(stat -c '%s' "$file")" rel="${file#${CANONICAL}/}" printf '%s\t%s\t%s\n' "$hash" "$bytes" "$rel" >>"$CANON_HASHES" done < <(find "$CANONICAL" -xdev -type f -print0) cut -f1 "$TMP_HASHES" | sort -u >"$TMP_HASH_ONLY" cut -f1 "$CANON_HASHES" | sort -u >"$CANON_HASH_ONLY" comm -12 "$TMP_HASH_ONLY" "$CANON_HASH_ONLY" >"$COMMON_HASHES" TMP_FILES="$(wc -l <"$TMP_HASHES" | tr -d ' ')" CANON_FILES="$(wc -l <"$CANON_HASHES" | tr -d ' ')" COMMON_UNIQUE_HASHES="$(wc -l <"$COMMON_HASHES" | tr -d ' ')" DUPLICATE_FILE_ROWS="$(awk -F '\t' ' NR==FNR {common[$1]=1; next} ($1 in common) {n++} END {print n+0} ' "$COMMON_HASHES" "$TMP_HASHES")" DUPLICATE_BYTES="$(awk -F '\t' ' NR==FNR {common[$1]=1; next} ($1 in common) {total+=$2} END {printf "%.0f", total+0} ' "$COMMON_HASHES" "$TMP_HASHES")" DUPLICATE_HUMAN="$(numfmt --to=iec-i --suffix=B "$DUPLICATE_BYTES" 2>/dev/null || printf '%sB' "$DUPLICATE_BYTES")" { printf 'tmpwip_esiste\tSI\n' printf 'canonical_esiste\tSI\n' printf 'file_tmpwip\t%s\n' "$TMP_FILES" printf 'file_canonical\t%s\n' "$CANON_FILES" printf 'hash_identici_distinti\t%s\n' "$COMMON_UNIQUE_HASHES" printf 'file_tmpwip_duplicati\t%s\n' "$DUPLICATE_FILE_ROWS" printf 'byte_tmpwip_duplicati\t%s\n' "$DUPLICATE_BYTES" printf 'spazio_tmpwip_duplicato\t%s\n' "$DUPLICATE_HUMAN" } >>"${WORKDIR}/06_TMPWIP_DUPLICATION.tsv" else { printf 'tmpwip_esiste\t%s\n' "$([[ -d "$TMPWIP" ]] && echo SI || echo NO)" printf 'canonical_esiste\t%s\n' "$([[ -d "$CANONICAL" ]] && echo SI || echo NO)" printf 'file_tmpwip\t0\n' printf 'file_canonical\t0\n' printf 'hash_identici_distinti\t0\n' printf 'file_tmpwip_duplicati\t0\n' printf 'byte_tmpwip_duplicati\t0\n' printf 'spazio_tmpwip_duplicato\t0B\n' } >>"${WORKDIR}/06_TMPWIP_DUPLICATION.tsv" fi log "[6/6] File più grandi ed esito" LARGEST_RAW="${WORKDIR}/.largest_candidates.tsv" : >"$LARGEST_RAW" for rel in "${CANDIDATES[@]}"; do root="${TARGET_DIR}/${rel}" [[ -d "$root" && ! -L "$root" ]] || continue find "$root" \ -xdev \ -type f \ -printf '%s\t%p\n' 2>>"$LOGFILE" \ >>"$LARGEST_RAW" done { printf 'byte\tspazio\tpercorso\n' sort -t $'\t' -rn -k1,1 "$LARGEST_RAW" \ | awk -F '\t' 'NR<=200 {print}' \ | 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}/07_LARGEST_CANDIDATE_FILES.tsv" ZERO_REFERENCE_BYTES=0 while IFS=$'\t' read -r area exists type bytes human files dirs; do [[ "$area" == "area" ]] && continue [[ "$exists" == "SI" && "$type" == "directory" ]] || continue key="$area" [[ "$area" == "components/templates/custom_templates/tmpwip" ]] && key="tmpwip" refs="$(awk -F '\t' -v a="$key" 'NR>1 && $1==a {print $2}' "${WORKDIR}/05_REFERENCE_SUMMARY.tsv")" [[ -n "$refs" ]] || refs=0 if [[ "$refs" == "0" ]]; then ZERO_REFERENCE_BYTES=$((ZERO_REFERENCE_BYTES + bytes)) fi done <"${WORKDIR}/01_CANDIDATE_SIZES.tsv" ZERO_REFERENCE_HUMAN="$(numfmt --to=iec-i --suffix=B "$ZERO_REFERENCE_BYTES" 2>/dev/null || printf '%sB' "$ZERO_REFERENCE_BYTES")" { printf 'voce\tvalore\n' printf 'aree_candidate_esistenti\t%s\n' "$EXISTING_COUNT" printf 'spazio_totale_candidate\t%s\n' "$TOTAL_HUMAN" printf 'file_codice_analizzati\t%s\n' "$CODE_FILE_COUNT" printf 'spazio_aree_senza_riferimenti_esterni\t%s\n' "$ZERO_REFERENCE_HUMAN" } >"${WORKDIR}/08_SUMMARY.tsv" { echo "AUDIT COMPLETATO" echo "Server: 215.6 / ax-accessi" echo "Target esclusivo: $TARGET_DIR" echo "Aree candidate esistenti: $EXISTING_COUNT" echo "Spazio totale aree candidate: $TOTAL_HUMAN" echo "File codice analizzati: $CODE_FILE_COUNT" echo "Spazio delle aree senza riferimenti esterni: $ZERO_REFERENCE_HUMAN" echo "Nessuna modifica eseguita." echo "Altri portali custom toccati: NO" } >"${WORKDIR}/99_SUMMARY.txt" report "Aree candidate esistenti: $EXISTING_COUNT." report "Spazio totale candidato: $TOTAL_HUMAN." report "Spazio senza riferimenti esterni: $ZERO_REFERENCE_HUMAN." report "Altri portali custom non toccati." log "AUDIT COMPLETATO: errori=${FAILURES}, avvisi=${WARNINGS}"