#!/bin/bash # ============================================================================= # NETGESCON - SCRIPT SINCRONIZZAZIONE DOCUMENTAZIONE # ============================================================================= # Script per sincronizzare la documentazione unificata tra: # - Server locale (sorgente) # - NAS/Storage remoto # - Google Drive # - Altri server di backup # # Creato: 18/07/2025 # Autore: Michele + GitHub Copilot # ============================================================================= # Configurazione colori RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configurazione base DOCS_SOURCE="$HOME/netgescon/docs/" LOG_FILE="$HOME/netgescon/log/sync-docs-$(date +%Y%m%d-%H%M%S).log" TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') CONFIG_FILE="$HOME/netgescon/sync-docs-config.env" # Crea directory log se non esiste mkdir -p "$HOME/netgescon/log" # Funzione di logging log() { local level=$1 shift local message="$*" echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" | tee -a "$LOG_FILE" } # Funzione di stampa colorata print_status() { local color=$1 local message=$2 echo -e "${color}$message${NC}" log "INFO" "$message" } # Funzione di controllo prerequisiti check_prerequisites() { print_status "$BLUE" "πŸ” Controllo prerequisiti..." # Verifica rsync if ! command -v rsync &> /dev/null; then print_status "$RED" "❌ ERRORE: rsync non installato" log "ERROR" "rsync non trovato nel sistema" exit 1 fi # Verifica directory sorgente if [ ! -d "$DOCS_SOURCE" ]; then print_status "$RED" "❌ ERRORE: Directory docs/ non trovata: $DOCS_SOURCE" log "ERROR" "Directory sorgente non trovata: $DOCS_SOURCE" exit 1 fi # Verifica file chiave local key_files=( "00-INDICE-DOCS-UNIFICATA.md" "00-COPILOT-MASTER-GUIDE.md" "00-transizione-linux/README-TRANSITION-COMPLETE.md" "00-transizione-linux/FEATURES-INVENTORY-COMPLETE.md" ) for file in "${key_files[@]}"; do if [ ! -f "$DOCS_SOURCE$file" ]; then print_status "$RED" "❌ ERRORE: File chiave mancante: $file" log "ERROR" "File chiave mancante: $DOCS_SOURCE$file" exit 1 fi done print_status "$GREEN" "βœ… Tutti i prerequisiti soddisfatti" } # Funzione di statistiche pre-sync show_stats() { print_status "$BLUE" "πŸ“Š Statistiche documentazione da sincronizzare:" local total_files=$(find "$DOCS_SOURCE" -type f | wc -l) local md_files=$(find "$DOCS_SOURCE" -name "*.md" | wc -l) local img_files=$(find "$DOCS_SOURCE" -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.gif" | wc -l) local sh_files=$(find "$DOCS_SOURCE" -name "*.sh" | wc -l) local total_size=$(du -sh "$DOCS_SOURCE" | cut -f1) echo " πŸ“„ File totali: $total_files" echo " πŸ“ File Markdown: $md_files" echo " πŸ–ΌοΈ Immagini: $img_files" echo " βš™οΈ Script: $sh_files" echo " πŸ’Ύ Dimensione totale: $total_size" echo "" log "STATS" "File totali: $total_files, MD: $md_files, IMG: $img_files, SH: $sh_files, Size: $total_size" } # Funzione di sincronizzazione generica sync_to_destination() { local dest_name=$1 local dest_path=$2 local options=$3 print_status "$YELLOW" "πŸ”„ Sincronizzazione verso $dest_name..." print_status "$BLUE" " Destinazione: $dest_path" # Prepara opzioni rsync local rsync_opts="-avz --progress --delete --exclude='.git' --exclude='*.tmp' --exclude='*~'" if [ -n "$options" ]; then rsync_opts="$rsync_opts $options" fi # Crea directory destinazione se necessario (per percorsi locali) if [[ "$dest_path" != *":"* ]]; then mkdir -p "$dest_path" fi # Esegui sincronizzazione local sync_start=$(date +%s) if eval rsync $rsync_opts "$DOCS_SOURCE" "$dest_path" 2>&1 | tee -a "$LOG_FILE"; then local sync_end=$(date +%s) local sync_duration=$((sync_end - sync_start)) print_status "$GREEN" "βœ… Sincronizzazione completata verso $dest_name (${sync_duration}s)" log "SUCCESS" "Sync completata verso $dest_name in ${sync_duration}s" return 0 else print_status "$RED" "❌ ERRORE durante sincronizzazione verso $dest_name" log "ERROR" "Sync fallita verso $dest_name" return 1 fi } # Configurazione destinazioni setup_destinations() { print_status "$BLUE" "πŸ“‹ Configurazione destinazioni di sincronizzazione..." # Carica configurazioni dal file if [ -f "$CONFIG_FILE" ]; then source "$CONFIG_FILE" log "INFO" "Configurazione caricata da: $CONFIG_FILE" else print_status "$YELLOW" "⚠️ File configurazione non trovato: $CONFIG_FILE" print_status "$BLUE" " Uso configurazione di default (solo backup locale)" fi # Array associativo per destinazioni attive declare -A destinations # Carica destinazioni dal file di configurazione # Solo le variabili definite e non vuote vengono aggiunte # Backup locali [ -n "${BACKUP_LOCAL:-}" ] && destinations["BACKUP_LOCAL"]="$BACKUP_LOCAL" [ -n "${BACKUP_EXTERNAL:-}" ] && destinations["BACKUP_EXTERNAL"]="$BACKUP_EXTERNAL" # Server remoti [ -n "${SERVER_PRODUCTION:-}" ] && destinations["SERVER_PRODUCTION"]="$SERVER_PRODUCTION" [ -n "${SERVER_DEV:-}" ] && destinations["SERVER_DEV"]="$SERVER_DEV" [ -n "${SERVER_BACKUP:-}" ] && destinations["SERVER_BACKUP"]="$SERVER_BACKUP" # Cloud storage [ -n "${GOOGLE_DRIVE:-}" ] && destinations["GOOGLE_DRIVE"]="$GOOGLE_DRIVE" [ -n "${DROPBOX:-}" ] && destinations["DROPBOX"]="$DROPBOX" [ -n "${ONEDRIVE:-}" ] && destinations["ONEDRIVE"]="$ONEDRIVE" # NAS e storage di rete [ -n "${NAS_SSH:-}" ] && destinations["NAS_SSH"]="$NAS_SSH" [ -n "${NAS_SMB:-}" ] && destinations["NAS_SMB"]="$NAS_SMB" [ -n "${FTP_SERVER:-}" ] && destinations["FTP_SERVER"]="$FTP_SERVER" # Se nessuna destinazione configurata, aggiungi backup locale di default if [ ${#destinations[@]} -eq 0 ]; then destinations["BACKUP_LOCAL"]="$HOME/netgescon-backup/docs/" print_status "$YELLOW" " Nessuna destinazione configurata, uso backup locale di default" fi # Mostra destinazioni configurate print_status "$BLUE" " Destinazioni configurate:" for dest in "${!destinations[@]}"; do echo " - $dest: ${destinations[$dest]}" done echo "" # Ritorna le destinazioni configurate con opzioni personalizzate for dest in "${!destinations[@]}"; do local dest_path="${destinations[$dest]}" local dest_opts_var="${dest}_OPTS" local dest_opts="${!dest_opts_var:-}" echo "$dest:$dest_path:$dest_opts" done } # Funzione principale di sincronizzazione perform_sync() { print_status "$BLUE" "πŸš€ Avvio sincronizzazione documentazione NetGescon" echo "" local destinations_list=$(setup_destinations) local sync_success=0 local sync_total=0 # Per ogni destinazione configurata while IFS=':' read -r dest_name dest_path dest_options; do if [ -n "$dest_name" ] && [ -n "$dest_path" ]; then sync_total=$((sync_total + 1)) # Conferma prima della sincronizzazione (per destinazioni critiche) if [[ "$dest_path" == *"@"* ]] || [[ "$dest_path" == *":"* ]]; then print_status "$YELLOW" "⚠️ Sincronizzazione remota verso $dest_name" read -p "Continuare? (y/N): " confirm if [[ "$confirm" != [yY] ]]; then print_status "$YELLOW" "⏭️ Saltata sincronizzazione verso $dest_name" continue fi fi if sync_to_destination "$dest_name" "$dest_path" "$dest_options"; then sync_success=$((sync_success + 1)) fi echo "" fi done <<< "$destinations_list" # Riepilogo finale print_status "$BLUE" "πŸ“‹ RIEPILOGO SINCRONIZZAZIONE:" echo " βœ… Successi: $sync_success/$sync_total" echo " πŸ“ Log completo: $LOG_FILE" echo " πŸ•’ Completato: $TIMESTAMP" if [ $sync_success -eq $sync_total ]; then print_status "$GREEN" "πŸŽ‰ Tutte le sincronizzazioni completate con successo!" log "SUCCESS" "Tutte le sincronizzazioni completate" return 0 else print_status "$YELLOW" "⚠️ Alcune sincronizzazioni sono fallite. Controllare il log." log "WARNING" "Sincronizzazioni parziali: $sync_success/$sync_total" return 1 fi } # Funzione di verifica post-sync verify_sync() { local dest_path=$1 if [[ "$dest_path" == *":"* ]]; then # Destinazione remota - verifica limitata return 0 fi if [ -d "$dest_path" ]; then local dest_files=$(find "$dest_path" -type f | wc -l) local source_files=$(find "$DOCS_SOURCE" -type f | wc -l) if [ "$dest_files" -eq "$source_files" ]; then print_status "$GREEN" "βœ… Verifica OK: $dest_files file sincronizzati" return 0 else print_status "$YELLOW" "⚠️ Possibile problema: source=$source_files, dest=$dest_files" return 1 fi else print_status "$RED" "❌ Directory destinazione non trovata" return 1 fi } # Funzione di aiuto show_help() { cat << EOF NETGESCON - Script Sincronizzazione Documentazione UTILIZZO: $0 [opzione] OPZIONI: --help, -h Mostra questo aiuto --stats Mostra solo statistiche senza sincronizzare --check Controlla solo prerequisiti --dry-run Simula sincronizzazione senza modificare file --force Sincronizza senza conferme interattive ESEMPI: $0 # Sincronizzazione normale con conferme $0 --stats # Solo statistiche $0 --dry-run # Test senza modifiche $0 --force # Sincronizzazione automatica CONFIGURAZIONE: Modifica la funzione setup_destinations() per aggiungere/rimuovere destinazioni. Le destinazioni remote richiedono configurazione SSH/rclone appropriata. LOG: I log vengono salvati in: $HOME/netgescon/log/ EOF } # Main - Parsing argomenti e esecuzione main() { case "${1:-}" in --help|-h) show_help exit 0 ;; --stats) check_prerequisites show_stats exit 0 ;; --check) check_prerequisites print_status "$GREEN" "βœ… Sistema pronto per la sincronizzazione" exit 0 ;; --dry-run) print_status "$YELLOW" "πŸ” MODALITΓ€ DRY-RUN (nessuna modifica effettiva)" # TODO: Implementare dry-run con --dry-run in rsync check_prerequisites show_stats print_status "$BLUE" "In modalitΓ  dry-run, usare rsync con --dry-run" exit 0 ;; --force) print_status "$YELLOW" "⚑ MODALITΓ€ FORCE (senza conferme)" export SYNC_FORCE_MODE=1 ;; "") # ModalitΓ  normale ;; *) echo "Opzione non riconosciuta: $1" echo "Usare --help per vedere le opzioni disponibili" exit 1 ;; esac # Esecuzione normale print_status "$BLUE" "🏁 AVVIO SINCRONIZZAZIONE NETGESCON DOCS" echo "==================================================" check_prerequisites show_stats perform_sync print_status "$BLUE" "🏁 Sincronizzazione terminata" } # Esegui se chiamato direttamente if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi