<# install-AdHoc-Backup.ps1 Menù di installazione / pianificazione / configurazione per AdHoc-Backup.ps1 #> # ========================== # CONFIGURAZIONE INIZIALE # ========================== # Cartella dove installeremo script e config $InstallRoot = "C:\polo\script" # Nome dello script di backup vero e proprio $BackupScriptName = "AdHoc-Backup.ps1" # Nome del file di configurazione $ConfigFileName = "backup.conf" # Qui mettiamo direttamente i tuoi link $DownloadMap = @{ "AdHoc-Backup.ps1" = "https://gitea.poloinformatico.it/Mattia/Backup-AdHoc/raw/branch/main/AdHoc-Backup.ps1" "backup.conf" = "https://gitea.poloinformatico.it/Mattia/Backup-AdHoc/raw/branch/main/backup.conf" } # ========================== # FUNZIONI DI SUPPORTO # ========================== function Ensure-Folder { param([string]$Path) if (-not (Test-Path $Path)) { Write-Host "Creo la cartella $Path ..." -ForegroundColor Yellow New-Item -ItemType Directory -Path $Path -Force | Out-Null } } function Download-File { param( [string]$Url, [string]$Destination ) try { Write-Host "Scarico $Url -> $Destination" Invoke-WebRequest -Uri $Url -OutFile $Destination -UseBasicParsing } catch { Write-Warning "Impossibile scaricare $Url. Errore: $($_.Exception.Message)" } } function Read-YesNo { param( [string]$Message, [bool]$Default = $true ) if ($Default) { $msg = "$Message [S/n]" } else { $msg = "$Message [s/N]" } $ans = Read-Host $msg if ([string]::IsNullOrWhiteSpace($ans)) { return $Default } $ans = $ans.Trim().ToLower() return $ans.StartsWith("s") } function Get-ConfigValue { param( [string]$Path, [string]$Key ) if (-not (Test-Path $Path)) { return "" } $line = Get-Content $Path | Where-Object { $_ -match "^\s*$([regex]::Escape($Key))\s*=" } | Select-Object -First 1 if ($null -eq $line) { return "" } return ($line -split "=",2)[1].Trim() } function Set-ConfigValue { param( [string]$Path, [string]$Key, [string]$Value ) $Value = $Value.Trim() if (-not (Test-Path $Path)) { "$Key=$Value" | Set-Content -Path $Path -Encoding UTF8 return } $content = Get-Content $Path $found = $false for ($i = 0; $i -lt $content.Count; $i++) { if ($content[$i] -match "^\s*$([regex]::Escape($Key))\s*=") { $content[$i] = "$Key=$Value" $found = $true break } } if (-not $found) { $content += "$Key=$Value" } $content | Set-Content -Path $Path -Encoding UTF8 } function Ensure-DefaultConfig { param([string]$ConfigPath) if (Test-Path $ConfigPath) { return } Write-Host "File di configurazione non trovato, ne creo uno di base..." -ForegroundColor Yellow @" # backup.conf generato automaticamente # Modificalo con l'opzione 3 del menù. BackupRoot=C:\Backups_AdHoc LocalRetentionDaysFiles=2 LocalRetentionDaysDb=2 RemoteRetentionDays=15 KeepLocalArchives=true EnableFileBackup=true EnableRcloneUpload=true ArchiveSources=C:\Zucchetti\ahr90|C:\Zucchetti\NetSetup EnableSqlBackup=true SqlInstance=localhost\SQLEXPRESS SqlUseWindowsAuth=true SqlUser=sa SqlPassword= DbInclude= DbExclude=master|model|msdb|tempdb SqlCompressStage=true SqlDropBakAfterZip=true SevenZipCompressionLevel=1 RcloneRemoteDest=dropbox:/Backups_AdHoc/%COMPUTERNAME% RcloneBwl= RcloneExtraArgs= MailEnabled=true MailSmtpHost=relay.poloinformatico.it MailSmtpPort=587 MailUseAuth=true MailUser= MailPassword= MailFrom=backup@localhost MailTo=it@poloinformatico.it MailSubjectPref=[BACKUP ADHOC] "@ | Set-Content -Path $ConfigPath -Encoding UTF8 } # ========================== # FUNZIONE 1: INSTALLA # ========================== function Install-AdHocBackup { Write-Host "== INSTALLAZIONE SCRIPT BACKUP ==" -ForegroundColor Cyan Ensure-Folder -Path $InstallRoot foreach ($entry in $DownloadMap.GetEnumerator()) { $fileName = $entry.Key $url = $entry.Value $dest = Join-Path $InstallRoot $fileName Download-File -Url $url -Destination $dest } $configPath = Join-Path $InstallRoot $ConfigFileName Ensure-DefaultConfig -ConfigPath $configPath # Chiede subito se vuole pianificare if (Read-YesNo "Vuoi creare una pianificazione (operazione consigliata)?" $true) { Show-ScheduleMenu } # Chiede subito se vuole modificare configurazione if (Read-YesNo "Vuoi modificare adesso la configurazione del file backup.conf?" $false) { Edit-BackupConfig -ConfigPath $configPath } Write-Host "Installazione completata." -ForegroundColor Green } # ========================== # FUNZIONE 2: PIANIFICAZIONE # ========================== function Create-BackupScheduledTask { param( [ValidateSet("Daily","Weekly")] [string]$Mode = "Daily" ) $backupScriptPath = Join-Path $InstallRoot $BackupScriptName if (-not (Test-Path $backupScriptPath)) { Write-Warning "Lo script di backup non è stato trovato in $backupScriptPath. Installa prima (opzione 1)." return } Write-Host "" Write-Host "Impostazione orario di esecuzione" -ForegroundColor Cyan $hour = Read-Host "Inserisci l'ora di esecuzione (0-23) [default 22]" if ([string]::IsNullOrWhiteSpace($hour)) { $hour = 22 } $minute = Read-Host "Inserisci i minuti (0-59) [default 30]" if ([string]::IsNullOrWhiteSpace($minute)) { $minute = 30 } $time = New-TimeSpan -Hours ([int]$hour) -Minutes ([int]$minute) $at = (Get-Date).Date + $time if ($Mode -eq "Weekly") { $day = Read-Host "Giorno della settimana (Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday) [default Monday]" if ([string]::IsNullOrWhiteSpace($day)) { $day = "Monday" } $trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek $day -At $at } else { $trigger = New-ScheduledTaskTrigger -Daily -At $at } $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$backupScriptPath`"" $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries $taskName = "Backup AdHoc" Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null Write-Host "Pianificazione '$taskName' creata in modalità $Mode alle $hour`:$minute." -ForegroundColor Green } function Show-ScheduleMenu { Write-Host "== CREA PIANIFICAZIONE ==" -ForegroundColor Cyan Write-Host "1) Giornaliera" Write-Host "2) Settimanale" Write-Host "0) Annulla" $choice = Read-Host "Seleziona" switch ($choice) { "1" { Create-BackupScheduledTask -Mode Daily } "2" { Create-BackupScheduledTask -Mode Weekly } default { Write-Host "Nessuna pianificazione creata." } } } # ========================== # FUNZIONE 3: MODIFICA CONFIG # ========================== function Edit-BackupConfig { param( [string]$ConfigPath ) if (-not (Test-Path $ConfigPath)) { Write-Warning "File $ConfigPath non trovato. Lo creo adesso." Ensure-DefaultConfig -ConfigPath $ConfigPath } $Descriptions = [ordered]@{ "BackupRoot" = "Cartella radice dove vanno archivi, log e tool." "LocalRetentionDaysFiles" = "Giorni di conservazione FILE in locale." "LocalRetentionDaysDb" = "Giorni di conservazione DATABASE in locale." "RemoteRetentionDays" = "Giorni di conservazione su destinazione remota (rclone)." "KeepLocalArchives" = "true = tiene una copia locale dopo l'upload." "EnableFileBackup" = "true = esegue il backup delle cartelle in ArchiveSources." "EnableRcloneUpload" = "true = dopo il backup carica su cloud tramite rclone." "ArchiveSources" = "Elenco cartelle/sorgenti da salvare, separate da | (pipe)." "EnableSqlBackup" = "true = fa anche i backup dei database SQL Server." "SqlInstance" = "Nome/istanza SQL Server (es. localhost\SQLEXPRESS)." "SqlUseWindowsAuth" = "true = usa utente Windows; false = usa SqlUser/SqlPassword." "SqlUser" = "Utente SQL (se SqlUseWindowsAuth=false)." "SqlPassword" = "Password SQL (se SqlUseWindowsAuth=false)." "DbInclude" = "Elenco DB da includere (se vuoto li prende tutti tranne gli esclusi)." "DbExclude" = "DB da escludere quando DbInclude è vuoto." "SqlCompressStage" = "true = comprime i .bak in .7z." "SqlDropBakAfterZip" = "true = elimina i .bak dopo la compressione." "SevenZipCompressionLevel" = "0..9 livello di compressione 7z (1=veloce, 9=max)." "RcloneRemoteDest" = "Destinazione rclone: REMOTO:percorso." "RcloneBwl" = "Limite banda rclone (es. 10M) oppure vuoto." "RcloneExtraArgs" = "Argomenti extra rclone separati da |." "MailEnabled" = "true = invia mail di report." "MailSmtpHost" = "Server SMTP/relay." "MailSmtpPort" = "Porta SMTP (es. 587)." "MailUseAuth" = "true = il relay richiede utente/password." "MailUser" = "Utente SMTP." "MailPassword" = "Password SMTP." "MailFrom" = "Mittente mail." "MailTo" = "Destinatari (separati da |)." "MailSubjectPref" = "Prefisso dell'oggetto mail." } Write-Host "== MODIFICA GUIDATA backup.conf ==" -ForegroundColor Cyan foreach ($key in $Descriptions.Keys) { $current = Get-ConfigValue -Path $ConfigPath -Key $key Write-Host "" Write-Host "$key" -ForegroundColor Yellow Write-Host " $($Descriptions[$key])" Write-Host " Valore attuale: $current" $newVal = Read-Host " Nuovo valore (invio per lasciare quello attuale)" if (-not [string]::IsNullOrWhiteSpace($newVal)) { Set-ConfigValue -Path $ConfigPath -Key $key -Value $newVal Write-Host " -> Aggiornato." } else { Write-Host " -> Lasciato invariato." } } Write-Host "" Write-Host "Configurazione aggiornata in $ConfigPath" -ForegroundColor Green } # ========================== # MENÙ PRINCIPALE # ========================== do { Write-Host "" Write-Host "==============================" -ForegroundColor DarkCyan Write-Host " INSTALL ADHOC BACKUP - MENU" Write-Host "==============================" -ForegroundColor DarkCyan Write-Host "1) Installa / aggiorna script (scarica da gitea)" Write-Host "2) Crea pianificazione (giornaliera/settimanale, con orario)" Write-Host "3) Modifica configurazione backup.conf (guidata)" Write-Host "0) Esci" $sel = Read-Host "Seleziona" $configPath = Join-Path $InstallRoot $ConfigFileName switch ($sel) { "1" { Install-AdHocBackup } "2" { Show-ScheduleMenu } "3" { Edit-BackupConfig -ConfigPath $configPath } "0" { break } default { Write-Host "Scelta non valida." -ForegroundColor Red } } } while ($true) Write-Host "Uscita dallo script." -ForegroundColor Cyan