Backup-AdHoc/install-AdHoc-Backup.ps1

347 lines
12 KiB
PowerShell

<#
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"
# (OPZIONALE) Base URL da cui scaricare i file
# Metti l'URL del tuo webserver / share http se li distribuisci così
$DownloadBaseUrl = "" # es. "https://intranet/polo/scripts"
# Elenco dei file da scaricare in modalità "installa lo script"
$FilesToDownload = @(
$BackupScriptName,
$ConfigFileName
)
# ==========================
# 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
)
if ([string]::IsNullOrWhiteSpace($Url)) {
Write-Warning "URL non impostato per $Destination, salto il download."
return
}
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 ($f in $FilesToDownload) {
$dest = Join-Path $InstallRoot $f
if (-not [string]::IsNullOrWhiteSpace($DownloadBaseUrl)) {
$url = ($DownloadBaseUrl.TrimEnd('/')) + "/" + $f
Download-File -Url $url -Destination $dest
} else {
# Se non abbiamo URL, non sovrascriviamo: assumiamo che lo script sia già nella stessa cartella
if (-not (Test-Path $dest)) {
Write-Warning "File $f non trovato e nessun URL impostato. Copialo manualmente in $InstallRoot."
}
}
}
$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
}
# Ora di esecuzione
$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`""
# Eseguiamo come SYSTEM con privilegi alti
$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." -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
}
# Descrizioni in italiano per aiutare l'utente
$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 o indirizzo dell'istanza SQL Server (es. localhost\SQLEXPRESS)."
"SqlUseWindowsAuth" = "true = usa l'utente Windows corrente; 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 uno .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"
Write-Host "2) Crea pianificazione (giornaliera/settimanale)"
Write-Host "3) Modifica configurazione backup.conf"
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