📋 Commit iniziale con: - ✅ Documentazione unificata in docs/ - ✅ Codice Laravel in netgescon-laravel/ - ✅ Script automazione in scripts/ - ✅ Configurazione sync rsync - ✅ Struttura organizzata e pulita 🔄 Versione: 2025.07.19-1644 🎯 Sistema pronto per Git distribuito
354 lines
11 KiB
PowerShell
354 lines
11 KiB
PowerShell
# 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
|