#!/bin/bash # NetGescon Auto-Sync Bash Script # Sincronizzazione automatica tra WSL/Linux e server remoto # Versione: 2.0 # Data: 2025-01-17 set -euo pipefail # Configurazione LOCAL_PATH="$HOME/netgescon/netgescon-laravel" REMOTE_HOST="192.168.0.43" REMOTE_USER="michele" REMOTE_PATH="/var/www/netgescon" BACKUP_DIR="$HOME/netgescon/backup/sync" LOG_FILE="$HOME/netgescon/log/auto-sync.log" # Opzioni default MODE="sync" TARGET="remote" FORCE=false VERBOSE=false DRY_RUN=false AUTO_RESTART=false # Colori per output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Funzioni utility log() { local message="$1" local level="${2:-INFO}" local timestamp=$(date "+%Y-%m-%d %H:%M:%S") local log_entry="[$timestamp] [$level] $message" # Crea directory log se non esiste mkdir -p "$(dirname "$LOG_FILE")" # Scrivi nel log echo "$log_entry" >> "$LOG_FILE" # Output colorato se verbose o errore if [[ "$VERBOSE" == "true" || "$level" == "ERROR" ]]; then case "$level" in "ERROR") echo -e "${RED}$log_entry${NC}" >&2 ;; "WARN") echo -e "${YELLOW}$log_entry${NC}" ;; "SUCCESS") echo -e "${GREEN}$log_entry${NC}" ;; *) echo -e "${NC}$log_entry${NC}" ;; esac fi } show_usage() { cat << EOF NetGescon Auto-Sync Script Uso: $0 [OPZIONI] Modalità: -m, --mode MODE Modalità operazione (sync|deploy|backup|status) [default: sync] -t, --target TARGET Target operazione (remote|local|both) [default: remote] Opzioni: -f, --force Forza operazioni senza backup -v, --verbose Output dettagliato -d, --dry-run Simulazione senza modifiche -r, --auto-restart Riavvia servizi automaticamente -h, --help Mostra questo aiuto Esempi: $0 # Sync completo $0 -m status -v # Mostra stato dettagliato $0 -m sync -f -r # Sync forzato con riavvio $0 -m backup -t both # Backup locale e remoto $0 -d -m sync # Simula sync senza modifiche EOF } parse_args() { while [[ $# -gt 0 ]]; do case $1 in -m|--mode) MODE="$2" shift 2 ;; -t|--target) TARGET="$2" shift 2 ;; -f|--force) FORCE=true shift ;; -v|--verbose) VERBOSE=true shift ;; -d|--dry-run) DRY_RUN=true shift ;; -r|--auto-restart) AUTO_RESTART=true shift ;; -h|--help) show_usage exit 0 ;; *) echo "Opzione sconosciuta: $1" >&2 show_usage exit 1 ;; esac done } test_remote_connection() { log "Testando connessione al server remoto..." if ssh -o ConnectTimeout=10 -o BatchMode=yes "$REMOTE_USER@$REMOTE_HOST" "echo 'Connected'" >/dev/null 2>&1; then log "Connessione remota OK" "SUCCESS" return 0 else log "Errore connessione remota" "ERROR" return 1 fi } backup_local() { log "Creando backup locale..." local backup_path="$BACKUP_DIR/local-$(date +%Y%m%d-%H%M%S)" mkdir -p "$BACKUP_DIR" if [[ "$DRY_RUN" == "true" ]]; then log "DRY RUN: Backup locale verso $backup_path" "WARN" return 0 fi if cp -r "$LOCAL_PATH" "$backup_path" 2>/dev/null; then log "Backup locale creato: $backup_path" "SUCCESS" return 0 else log "Errore durante backup locale" "ERROR" return 1 fi } backup_remote() { log "Creando backup remoto..." local timestamp=$(date +%Y%m%d-%H%M%S) local backup_cmd="sudo cp -r $REMOTE_PATH ${REMOTE_PATH}_backup_$timestamp" if [[ "$DRY_RUN" == "true" ]]; then log "DRY RUN: $backup_cmd" "WARN" return 0 fi if ssh "$REMOTE_USER@$REMOTE_HOST" "$backup_cmd" 2>/dev/null; then log "Backup remoto creato: ${REMOTE_PATH}_backup_$timestamp" "SUCCESS" return 0 else log "Errore durante backup remoto" "ERROR" return 1 fi } sync_to_remote() { log "Sincronizzando verso server remoto..." # Costruisci exclude pattern per rsync local exclude_args=( "--exclude=node_modules/" "--exclude=vendor/" "--exclude=storage/logs/" "--exclude=storage/framework/cache/" "--exclude=storage/framework/sessions/" "--exclude=storage/framework/views/" "--exclude=.git/" "--exclude=*.log" "--exclude=.env.local" "--exclude=.env.backup" ) local rsync_cmd=( "rsync" "-avz" "--delete" "${exclude_args[@]}" "$LOCAL_PATH/" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/" ) if [[ "$DRY_RUN" == "true" ]]; then log "DRY RUN: ${rsync_cmd[*]}" "WARN" return 0 fi log "Eseguendo rsync: ${rsync_cmd[*]}" if "${rsync_cmd[@]}" 2>/dev/null; then log "Sincronizzazione completata con successo" "SUCCESS" return 0 else log "Errore durante sincronizzazione" "ERROR" return 1 fi } deploy_remote() { log "Eseguendo deploy sul server remoto..." local deploy_commands=( "cd $REMOTE_PATH" "sudo chown -R www-data:www-data ." "sudo chmod -R 755 ." "sudo chmod -R 777 storage/" "sudo chmod -R 777 bootstrap/cache/" "composer install --no-dev --optimize-autoloader" "php artisan config:cache" "php artisan route:cache" "php artisan view:cache" ) if [[ "$AUTO_RESTART" == "true" ]]; then deploy_commands+=( "sudo systemctl restart nginx" "sudo systemctl restart php8.3-fpm" ) fi local full_command IFS=' && ' eval 'full_command="${deploy_commands[*]}"' if [[ "$DRY_RUN" == "true" ]]; then log "DRY RUN: $full_command" "WARN" return 0 fi log "Eseguendo deploy remoto..." if ssh "$REMOTE_USER@$REMOTE_HOST" "$full_command" 2>/dev/null; then log "Deploy completato con successo" "SUCCESS" return 0 else log "Errore durante deploy" "ERROR" return 1 fi } run_migrations() { log "Eseguendo migrazioni sul server remoto..." local migration_commands=( "cd $REMOTE_PATH" "php artisan migrate --force" ) local full_command IFS=' && ' eval 'full_command="${migration_commands[*]}"' if [[ "$DRY_RUN" == "true" ]]; then log "DRY RUN: $full_command" "WARN" return 0 fi if ssh "$REMOTE_USER@$REMOTE_HOST" "$full_command" 2>/dev/null; then log "Migrazioni completate con successo" "SUCCESS" return 0 else log "Errore durante migrazioni" "ERROR" return 1 fi } show_status() { log "Controllando stato del sistema..." # Status locale echo -e "\n${CYAN}=== STATUS LOCALE ===${NC}" echo "Path: $LOCAL_PATH" echo "Esistenza: $(test -d "$LOCAL_PATH" && echo "true" || echo "false")" if [[ -d "$LOCAL_PATH" ]]; then local file_count=$(find "$LOCAL_PATH" -type f | wc -l) echo "File totali: $file_count" local last_modified=$(find "$LOCAL_PATH" -type f -exec stat -c '%Y %n' {} \; 2>/dev/null | sort -nr | head -1) echo "Ultima modifica: $last_modified" local disk_usage=$(du -sh "$LOCAL_PATH" 2>/dev/null | cut -f1) echo "Spazio disco: $disk_usage" fi # Status remoto echo -e "\n${CYAN}=== STATUS REMOTO ===${NC}" if test_remote_connection; then local remote_status remote_status=$(ssh "$REMOTE_USER@$REMOTE_HOST" " cd $REMOTE_PATH 2>/dev/null || exit 1 echo 'Path exists: true' echo 'Files count: \$(find . -type f | wc -l)' echo 'Last modified: \$(find . -type f -exec stat -c '%Y %n' {} \; | sort -nr | head -1)' echo 'Disk usage: \$(du -sh . | cut -f1)' echo 'Laravel version: \$(php artisan --version 2>/dev/null || echo \"N/A\")' echo 'Database status:' php artisan migrate:status 2>/dev/null | tail -5 || echo 'N/A' " 2>/dev/null) if [[ $? -eq 0 ]]; then echo "$remote_status" else echo -e "${RED}Errore nel recupero status remoto${NC}" fi fi } main() { log "=== NetGescon Auto-Sync Started ===" "SUCCESS" log "Modalità: $MODE, Target: $TARGET, Force: $FORCE, DryRun: $DRY_RUN" # Verifica connessione remota se necessario if [[ "$TARGET" == "remote" || "$TARGET" == "both" ]]; then if ! test_remote_connection; then log "Impossibile connettersi al server remoto. Uscita." "ERROR" exit 1 fi fi case "$MODE" in "status") show_status ;; "backup") if [[ "$TARGET" == "local" || "$TARGET" == "both" ]]; then backup_local || exit 1 fi if [[ "$TARGET" == "remote" || "$TARGET" == "both" ]]; then backup_remote || exit 1 fi ;; "sync") # Backup prima della sincronizzazione if [[ "$FORCE" != "true" ]]; then backup_local || { log "Backup locale fallito. Usa -f per continuare." "ERROR" exit 1 } backup_remote || { log "Backup remoto fallito. Usa -f per continuare." "ERROR" exit 1 } fi # Sincronizzazione sync_to_remote || exit 1 # Deploy automatico deploy_remote || exit 1 ;; "deploy") deploy_remote || exit 1 run_migrations || exit 1 ;; *) log "Modalità non riconosciuta: $MODE" "ERROR" show_usage exit 1 ;; esac log "=== NetGescon Auto-Sync Completed ===" "SUCCESS" } # Parse arguments and run main parse_args "$@" main