|
|
|
<#
|
|
.SYNOPSIS
|
|
Script oficial de automação de Backup (Full e Diferencial) para o banco Hemovida.
|
|
.DESCRIPTION
|
|
Executa a persistência no subsistema local, validação de integridade por metadados,
|
|
expurgo controlado de arquivos excedentes e tratamento de falhas com auto-recuperação da cadeia.
|
|
#>
|
|
|
|
param (
|
|
[Parameter(Mandatory=$false)]
|
|
[ValidateSet("Full", "Diff")]
|
|
[string]$TipoBackup = "Full"
|
|
)
|
|
|
|
# ============================================================================
|
|
# CABEÇALHO DE CONFIGURAÇÃO DE VARIÁVEIS (AJUSTADO PARA PRODUÇÃO)
|
|
# ============================================================================
|
|
$DiretorioBackup = "C:\Backup_Hemovida"
|
|
$PastaLogs = "$DiretorioBackup\Logs"
|
|
$BancoDados = "hemovida"
|
|
$StringConexao = "Server=.;Database=master;User Id=sa;Password=suasenhaqui;Encrypt=False;TrustServerCertificate=True;"
|
|
$MaxRetencaoFull = 2 # Mantém os últimos 2 backups Full
|
|
$MaxRetencaoDiff = 6 # Mantém os diferenciais recentes do ciclo ativo
|
|
$TimeoutComando = 7200 # Tempo limite em segundos (2 horas)
|
|
# ============================================================================
|
|
|
|
if (-not (Test-Path $PastaLogs)) {
|
|
New-Item -ItemType Directory -Force -Path $PastaLogs | Out-Null
|
|
}
|
|
|
|
$ArquivoLog = "$PastaLogs\Log_Backups_$(Get-Date -Format 'yyyy-MM').txt"
|
|
|
|
function Gravar-Log {
|
|
param([string]$Mensagem, [string]$Nivel="INFO")
|
|
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
$Linha = "[$Timestamp] [$Nivel] $Mensagem"
|
|
Add-Content -Path $ArquivoLog -Value $Linha
|
|
Write-Host $Linha
|
|
}
|
|
|
|
# ============================================================================
|
|
# BLINDAGEM DE SEGURANÇA: Verificação e Auto-Recuperação da Cadeia de Backup
|
|
# ============================================================================
|
|
if ($TipoBackup -eq "Diff") {
|
|
$UltimoFull = Get-ChildItem -Path $DiretorioBackup -Filter "Hemovida_Full_*.bak" | Where-Object { $_.CreationTime -gt (Get-Date).AddHours(-24) }
|
|
|
|
if (-not $UltimoFull) {
|
|
Write-Host "[WARNING] Nenhum Backup Full recente encontrado. Chaveando para Backup Full de segurança..." -ForegroundColor Yellow
|
|
if (Test-Path $ArquivoLog) {
|
|
Gravar-Log "Nenhum Backup Full recente encontrado no ciclo. Forçando Full de segurança antes do Diferencial..." "WARN"
|
|
}
|
|
$TipoBackup = "Full"
|
|
}
|
|
}
|
|
# ============================================================================
|
|
|
|
$DataStr = Get-Date -Format "yyyyMMdd_HHmm"
|
|
$ArquivoDestino = "$DiretorioBackup\Hemovida_$($TipoBackup)_$DataStr.bak"
|
|
|
|
if ($TipoBackup -eq "Full") {
|
|
$QueryBackup = "BACKUP DATABASE [$BancoDados] TO DISK = '$ArquivoDestino' WITH INIT, FORMAT, STATS = 10"
|
|
} else {
|
|
$QueryBackup = "BACKUP DATABASE [$BancoDados] TO DISK = '$ArquivoDestino' WITH DIFFERENTIAL, STATS = 10"
|
|
}
|
|
|
|
$QueryVerify = "RESTORE VERIFYONLY FROM DISK = '$ArquivoDestino'"
|
|
|
|
$MaxTentativas = 2
|
|
$Tentativa = 0
|
|
$Sucesso = $false
|
|
|
|
Gravar-Log "=== Iniciando Rotina de Backup $TipoBackup ===" "START"
|
|
|
|
while ($Tentativa -lt $MaxTentativas -and -not $Sucesso) {
|
|
$Tentativa++
|
|
$Conexao = $null
|
|
|
|
try {
|
|
Gravar-Log "Tentativa $Tentativa de $MaxTentativas para backup $TipoBackup..." "INFO"
|
|
|
|
$Conexao = New-Object System.Data.SqlClient.SqlConnection($StringConexao)
|
|
$Conexao.Open()
|
|
|
|
$Comando = $Conexao.CreateCommand()
|
|
$Comando.CommandTimeout = $TimeoutComando
|
|
|
|
Gravar-Log "Gravando dados no disco..." "INFO"
|
|
$Comando.CommandText = $QueryBackup
|
|
$Comando.ExecuteNonQuery() | Out-Null
|
|
|
|
Gravar-Log "Iniciando teste de integridade estrutural (RESTORE VERIFYONLY)..." "INFO"
|
|
$Comando.CommandText = $QueryVerify
|
|
$Comando.ExecuteNonQuery() | Out-Null
|
|
Gravar-Log "Integridade confirmada. O backup é perfeitamente restaurável." "SUCCESS"
|
|
|
|
# Regras de retenção dinâmicas baseadas no tipo de backup executado
|
|
if ($TipoBackup -eq "Full") {
|
|
Gravar-Log "Aplicando retenção de Full (Máximo: $MaxRetencaoFull cópias)..." "INFO"
|
|
$BackupsExistentes = Get-ChildItem -Path $DiretorioBackup -Filter "Hemovida_Full*.bak" | Sort-Object CreationTime -Descending
|
|
|
|
if ($BackupsExistentes.Count -gt $MaxRetencaoFull) {
|
|
$BackupsParaExcluir = $BackupsExistentes | Select-Object -Skip $MaxRetencaoFull
|
|
foreach ($bkp in $BackupsParaExcluir) {
|
|
Remove-Item -Path $bkp.FullName -Force
|
|
Gravar-Log "Backup Full antigo excluído: $($bkp.Name)" "WARN"
|
|
}
|
|
}
|
|
|
|
# Limpeza preventiva de diferenciais obsoletos gerados antes do novo ciclo Full
|
|
Gravar-Log "Expurgando diferenciais antigos do ciclo anterior..." "INFO"
|
|
Get-ChildItem -Path $DiretorioBackup -Filter "Hemovida_Diff*.bak" | Remove-Item -Force -ErrorAction SilentlyContinue
|
|
|
|
} else {
|
|
Gravar-Log "Aplicando retenção de Parciais/Diff (Máximo: $MaxRetencaoDiff cópias)..." "INFO"
|
|
$BackupsExistentes = Get-ChildItem -Path $DiretorioBackup -Filter "Hemovida_Diff*.bak" | Sort-Object CreationTime -Descending
|
|
|
|
if ($BackupsExistentes.Count -gt $MaxRetencaoDiff) {
|
|
$BackupsParaExcluir = $BackupsExistentes | Select-Object -Skip $MaxRetencaoDiff
|
|
foreach ($bkp in $BackupsParaExcluir) {
|
|
Remove-Item -Path $bkp.FullName -Force
|
|
Gravar-Log "Backup Parcial antigo excluído: $($bkp.Name)" "WARN"
|
|
}
|
|
}
|
|
}
|
|
|
|
Gravar-Log "Processo finalizado com absoluto SUCESSO!" "SUCCESS"
|
|
$Sucesso = $true
|
|
|
|
} catch {
|
|
Gravar-Log "Falha crítica no processo: $($_.Exception.Message)" "ERROR"
|
|
|
|
if ($Tentativa -lt $MaxTentativas) {
|
|
Gravar-Log "Entrando em modo de auto-recuperação. Aguardando 1 hora para nova tentativa..." "RETRY"
|
|
Start-Sleep -Seconds 3600
|
|
} else {
|
|
Gravar-Log "Tentativas esgotadas. O Backup $TipoBackup FALHOU DEFINITIVAMENTE." "FATAL"
|
|
}
|
|
} finally {
|
|
if ($null -ne $Conexao -and $Conexao.State -eq 'Open') {
|
|
$Conexao.Close()
|
|
$Conexao.Dispose()
|
|
}
|
|
}
|
|
}
|