#!/usr/bin/env bash set -Eeuo pipefail umask 022 # STEP025 - SERVER ATTESO: 215.6 / ax-accessi # # Dimostra se bower_components e node_modules sono: # - directory fisiche dentro presenze.distribuite; # - oppure symlink verso la release condivisa. # # Mostra separatamente: # - tipo reale del percorso (lstat); # - destinazione del link; # - byte occupati dal solo symlink; # - byte della directory condivisa; # - inode del percorso dereferenziato e inode della destinazione attesa. # # Nessuna modifica. START_DIR="$PWD" STAMP="$(date '+%Y%m%d_%H%M%S')" BASE="STEP025_2156_DISTRIBUITE_SYMLINK_PHYSICAL_SIZE_PROOF_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: $TARGET_DIR" 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)" for cmd in stat readlink du numfmt zip hostname grep xargs; do command -v "$cmd" >/dev/null 2>&1 || fail "comando mancante: $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" [[ -d "$SHARED_RELEASE" ]] || fail "release condivisa assente: $SHARED_RELEASE" [[ "$FAILURES" -eq 0 ]] || exit 21 printf 'libreria\tpath\ttipo_lstat\te_symlink\tlink_testuale\tlink_risolto\ttarget_atteso\tbyte_symlink\tbyte_target\tspazio_target\tinode_dereferenziato\tinode_target\tesito\n' \ >"${WORKDIR}/01_PROOF.tsv" GOOD=0 for lib in bower_components node_modules; do path="${TARGET_DIR}/${lib}" expected="${SHARED_RELEASE}/${lib}" type_lstat="$(stat -c '%F' "$path" 2>/dev/null || printf 'ASSENTE')" link_text="$(readlink "$path" 2>/dev/null || true)" resolved="$(readlink -f "$path" 2>/dev/null || true)" link_bytes="$(stat -c '%s' "$path" 2>/dev/null || printf '0')" if [[ -d "$expected" ]]; then target_bytes="$(du -sb -- "$expected" 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")" inode_target="$(stat -Lc '%d:%i' "$expected" 2>/dev/null || true)" else target_bytes=0 target_human="0B" inode_target="" fi inode_deref="$(stat -Lc '%d:%i' "$path" 2>/dev/null || true)" if [[ -L "$path" \ && "$resolved" == "$expected" \ && "$inode_deref" == "$inode_target" \ && -d "$expected" ]]; then is_link="SI" status="SYMLINK_CONDIVISO_OK" GOOD=$((GOOD + 1)) else is_link="NO" status="NON_CONFORME" fail "${path} non è il symlink condiviso atteso" fi printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \ "$lib" \ "$path" \ "$type_lstat" \ "$is_link" \ "$link_text" \ "$resolved" \ "$expected" \ "$link_bytes" \ "$target_bytes" \ "$target_human" \ "$inode_deref" \ "$inode_target" \ "$status" \ >>"${WORKDIR}/01_PROOF.tsv" done TARGET_BYTES_NO_DEREF="$(du -sb -- "$TARGET_DIR" 2>/dev/null | awk '{print $1}' || printf '0')" TARGET_HUMAN_NO_DEREF="$(numfmt --to=iec-i --suffix=B "$TARGET_BYTES_NO_DEREF" 2>/dev/null || printf '%sB' "$TARGET_BYTES_NO_DEREF")" { echo "AUDIT COMPLETATO" echo "Server: 215.6 / ax-accessi" echo "Target: $TARGET_DIR" echo "Symlink condivisi corretti: $GOOD/2" echo "Dimensione del portale senza seguire i symlink: $TARGET_HUMAN_NO_DEREF" echo echo "NOTA:" echo "Un client SFTP/IDE può seguire il symlink durante il download." echo "In quel caso sul PC viene copiata tutta la directory condivisa e appare" echo "con la sua dimensione reale, anche se sul server il percorso è un symlink." echo "Nessuna modifica eseguita." } >"${WORKDIR}/99_SUMMARY.txt" report "Symlink condivisi corretti: $GOOD/2." report "Dimensione target senza seguire i symlink: $TARGET_HUMAN_NO_DEREF." [[ "$FAILURES" -eq 0 ]] || exit 22 log "AUDIT COMPLETATO: symlink condivisi corretti=${GOOD}/2"