# NetGescon Auto-Sync PowerShell Script # Sincronizzazione automatica tra WSL/Windows e server remoto Linux # Versione: 2.0 # Data: 2025-01-17 param( [string]$Mode = "sync", # sync, deploy, backup, status [string]$Target = "remote", # remote, local, both [switch]$Force = $false, # Forza operazioni senza conferma [switch]$Verbose = $false, # Output dettagliato [switch]$DryRun = $false, # Simulazione senza modifiche [switch]$AutoRestart = $false # Riavvia automaticamente servizi ) # Configurazione $CONFIG = @{ LOCAL_PATH = "U:\home\michele\netgescon\netgescon-laravel" REMOTE_HOST = "192.168.0.43" REMOTE_USER = "michele" REMOTE_PATH = "/var/www/netgescon" BACKUP_DIR = "U:\home\michele\netgescon\backup\sync" LOG_FILE = "U:\home\michele\netgescon\log\auto-sync.log" EXCLUDE_PATTERNS = @( "node_modules/", "vendor/", "storage/logs/", "storage/framework/cache/", "storage/framework/sessions/", "storage/framework/views/", ".git/", "*.log", ".env.local", ".env.backup" ) } # Funzioni utility function Write-Log { param([string]$Message, [string]$Level = "INFO") $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logEntry = "[$timestamp] [$Level] $Message" if ($Verbose -or $Level -eq "ERROR") { Write-Host $logEntry -ForegroundColor $( switch ($Level) { "ERROR" { "Red" } "WARN" { "Yellow" } "SUCCESS" { "Green" } default { "White" } } ) } # Crea directory log se non esiste $logDir = Split-Path $CONFIG.LOG_FILE -Parent if (!(Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } Add-Content -Path $CONFIG.LOG_FILE -Value $logEntry } function Test-RemoteConnection { Write-Log "Testando connessione al server remoto..." $result = & ssh -o ConnectTimeout=10 -o BatchMode=yes "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" "echo 'Connected'" if ($LASTEXITCODE -eq 0) { Write-Log "Connessione remota OK" "SUCCESS" return $true } else { Write-Log "Errore connessione remota" "ERROR" return $false } } function Backup-Local { Write-Log "Creando backup locale..." $backupPath = Join-Path $CONFIG.BACKUP_DIR "local-$(Get-Date -Format 'yyyyMMdd-HHmmss')" if (!(Test-Path $CONFIG.BACKUP_DIR)) { New-Item -ItemType Directory -Path $CONFIG.BACKUP_DIR -Force | Out-Null } if ($DryRun) { Write-Log "DRY RUN: Backup locale verso $backupPath" "WARN" return $true } try { Copy-Item -Path $CONFIG.LOCAL_PATH -Destination $backupPath -Recurse -Force Write-Log "Backup locale creato: $backupPath" "SUCCESS" return $true } catch { Write-Log "Errore durante backup locale: $($_.Exception.Message)" "ERROR" return $false } } function Backup-Remote { Write-Log "Creando backup remoto..." $timestamp = Get-Date -Format "yyyyMMdd-HHmmss" $backupCmd = "sudo cp -r $($CONFIG.REMOTE_PATH) $($CONFIG.REMOTE_PATH)_backup_$timestamp" if ($DryRun) { Write-Log "DRY RUN: $backupCmd" "WARN" return $true } $result = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" $backupCmd if ($LASTEXITCODE -eq 0) { Write-Log "Backup remoto creato: $($CONFIG.REMOTE_PATH)_backup_$timestamp" "SUCCESS" return $true } else { Write-Log "Errore durante backup remoto" "ERROR" return $false } } function Sync-ToRemote { Write-Log "Sincronizzando verso server remoto..." # Costruisci exclude pattern per rsync $excludeArgs = @() foreach ($pattern in $CONFIG.EXCLUDE_PATTERNS) { $excludeArgs += "--exclude=$pattern" } $rsyncCmd = @( "rsync", "-avz", "--delete" ) + $excludeArgs + @( "$($CONFIG.LOCAL_PATH)/", "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST):$($CONFIG.REMOTE_PATH)/" ) if ($DryRun) { Write-Log "DRY RUN: $($rsyncCmd -join ' ')" "WARN" return $true } Write-Log "Eseguendo rsync: $($rsyncCmd -join ' ')" $result = & $rsyncCmd[0] $rsyncCmd[1..($rsyncCmd.Length-1)] if ($LASTEXITCODE -eq 0) { Write-Log "Sincronizzazione completata con successo" "SUCCESS" return $true } else { Write-Log "Errore durante sincronizzazione" "ERROR" return $false } } function Deploy-Remote { Write-Log "Eseguendo deploy sul server remoto..." $deployCommands = @( "cd $($CONFIG.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 ($AutoRestart) { $deployCommands += @( "sudo systemctl restart nginx", "sudo systemctl restart php8.3-fpm" ) } $fullCommand = $deployCommands -join " && " if ($DryRun) { Write-Log "DRY RUN: $fullCommand" "WARN" return $true } Write-Log "Eseguendo deploy remoto..." $result = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" $fullCommand if ($LASTEXITCODE -eq 0) { Write-Log "Deploy completato con successo" "SUCCESS" return $true } else { Write-Log "Errore durante deploy" "ERROR" return $false } } function Run-Migrations { Write-Log "Eseguendo migrazioni sul server remoto..." $migrationCommands = @( "cd $($CONFIG.REMOTE_PATH)", "php artisan migrate --force" ) $fullCommand = $migrationCommands -join " && " if ($DryRun) { Write-Log "DRY RUN: $fullCommand" "WARN" return $true } $result = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" $fullCommand if ($LASTEXITCODE -eq 0) { Write-Log "Migrazioni completate con successo" "SUCCESS" return $true } else { Write-Log "Errore durante migrazioni" "ERROR" return $false } } function Show-Status { Write-Log "Controllando stato del sistema..." # Status locale Write-Host "`n=== STATUS LOCALE ===" -ForegroundColor Cyan Write-Host "Path: $($CONFIG.LOCAL_PATH)" Write-Host "Esistenza: $(Test-Path $CONFIG.LOCAL_PATH)" if (Test-Path $CONFIG.LOCAL_PATH) { $localFiles = Get-ChildItem -Path $CONFIG.LOCAL_PATH -Recurse | Measure-Object Write-Host "File totali: $($localFiles.Count)" $lastModified = Get-ChildItem -Path $CONFIG.LOCAL_PATH -Recurse | Sort-Object LastWriteTime -Descending | Select-Object -First 1 Write-Host "Ultima modifica: $($lastModified.LastWriteTime) - $($lastModified.Name)" } # Status remoto Write-Host "`n=== STATUS REMOTO ===" -ForegroundColor Cyan if (Test-RemoteConnection) { $remoteStatus = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" @" cd $($CONFIG.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')" "@ if ($LASTEXITCODE -eq 0) { Write-Host $remoteStatus } else { Write-Host "Errore nel recupero status remoto" -ForegroundColor Red } } } # Main execution function Main { Write-Log "=== NetGescon Auto-Sync Started ===" "SUCCESS" Write-Log "Modalità: $Mode, Target: $Target, Force: $Force, DryRun: $DryRun" # Verifica connessione remota if ($Target -eq "remote" -or $Target -eq "both") { if (!(Test-RemoteConnection)) { Write-Log "Impossibile connettersi al server remoto. Uscita." "ERROR" exit 1 } } switch ($Mode) { "status" { Show-Status } "backup" { if ($Target -eq "local" -or $Target -eq "both") { if (!(Backup-Local)) { exit 1 } } if ($Target -eq "remote" -or $Target -eq "both") { if (!(Backup-Remote)) { exit 1 } } } "sync" { # Backup prima della sincronizzazione if (!$Force) { if (!(Backup-Local)) { Write-Log "Backup locale fallito. Usa -Force per continuare." "ERROR" exit 1 } if (!(Backup-Remote)) { Write-Log "Backup remoto fallito. Usa -Force per continuare." "ERROR" exit 1 } } # Sincronizzazione if (!(Sync-ToRemote)) { exit 1 } # Deploy automatico if (!(Deploy-Remote)) { exit 1 } } "deploy" { if (!(Deploy-Remote)) { exit 1 } if (!(Run-Migrations)) { exit 1 } } default { Write-Log "Modalità non riconosciuta: $Mode" "ERROR" Write-Host @" Uso: .\auto-sync.ps1 [OPZIONI] Modalità: -Mode sync Sincronizza e deploya (default) -Mode deploy Solo deploy remoto -Mode backup Solo backup -Mode status Mostra stato sistema Target: -Target remote Solo server remoto (default) -Target local Solo locale -Target both Entrambi Opzioni: -Force Forza operazioni senza backup -Verbose Output dettagliato -DryRun Simulazione senza modifiche -AutoRestart Riavvia servizi automaticamente Esempi: .\auto-sync.ps1 .\auto-sync.ps1 -Mode status -Verbose .\auto-sync.ps1 -Mode sync -Force -AutoRestart .\auto-sync.ps1 -Mode backup -Target both "@ exit 1 } } Write-Log "=== NetGescon Auto-Sync Completed ===" "SUCCESS" } # Esegui main Main