Public/New-sqmOlaUsrDbBackupJob.ps1
|
<# .SYNOPSIS Creates SQL Agent jobs for FULL, DIFF, and/or LOG backups of user databases via Ola Hallengren's DatabaseBackup. .DESCRIPTION Creates a separate SQL Agent job for each selected backup type (-Full, -Diff, -Log). Each job gets its own schedule with configurable days and start time. Backups are stored in <BackupDirectory>\Usr-db. Job names are read from the module configuration: OlaJobNameFull (Default: 'OlaHH-UserDatabases-FULL') OlaJobNameDiff (Default: 'OlaHH-UserDatabases-DIFF') OlaJobNameLog (Default: 'OlaHH-UserDatabases-LOG') When -UseExcludeTable is set, the function reads master.dbo.sqm_BackupExclude (created by Sync-sqmBackupExcludeTable) for entries where IsActive=1 AND IsOrphaned=0. If entries are found, they are passed to Ola's @ExcludeDatabases parameter in the generated job step command. If the table does not exist or contains no matching rows, the -Databases parameter is used unchanged. .PARAMETER SqlInstance SQL Server instance. Default: current computer name. .PARAMETER SqlCredential PSCredential for the SQL connection. .PARAMETER BackupDirectory Backup base directory. User databases are backed up to <BackupDirectory>\Usr-db. Default: automatically determined from SQL Server. .PARAMETER Databases Database filter for Ola. E.g. 'USER_DATABASES', 'ALL_DATABASES', or comma-separated DB names like 'DB1,DB2'. Default: 'USER_DATABASES'. .PARAMETER Full Creates a FULL backup job. .PARAMETER FullJobName Overrides the job name for FULL read from the configuration. .PARAMETER FullScheduleTime Start time of the FULL job in format 'HH:mm'. Default: '20:00'. .PARAMETER FullScheduleDays Days of the week for the FULL job as an array. Valid values: 'Monday'..'Sunday', 'Weekdays', 'Weekend', 'EveryDay'. Multiple days: @('Monday','Wednesday','Friday'). Default: @('Sunday'). .PARAMETER FullScheduleIntervalMinutes Repeat interval for the FULL job in minutes (e.g. 60 = hourly). 0 = no interval, job runs once at FullScheduleTime. Default: 0. .PARAMETER Diff Creates a DIFF backup job. .PARAMETER DiffJobName Overrides the job name for DIFF read from the configuration. .PARAMETER DiffScheduleTime Start time of the DIFF job in format 'HH:mm'. Default: '20:00'. .PARAMETER DiffScheduleDays Days of the week for the DIFF job. Default: @('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'). .PARAMETER DiffScheduleIntervalMinutes Repeat interval for the DIFF job in minutes. 0 = once. Default: 0. .PARAMETER Log Creates a LOG backup job. .PARAMETER LogJobName Overrides the job name for LOG read from the configuration. .PARAMETER LogScheduleTime Start time of the LOG job in format 'HH:mm'. Default: '00:00'. .PARAMETER LogScheduleDays Days of the week for the LOG job. Default: @('EveryDay'). .PARAMETER LogScheduleIntervalMinutes Repeat interval for the LOG job in minutes (e.g. 15 = every 15 minutes). 0 = once at LogScheduleTime. Default: 0. .PARAMETER JobCategory Category for all created jobs. Default: 'Database Maintenance'. .PARAMETER CleanupTime Age in hours after which backup files are deleted. Default: 48. 0 = no cleanup. .PARAMETER Compress Backup compression. Default: 'Y'. .PARAMETER Verify Backup verification. Default: 'Y'. .PARAMETER CheckSum Checksum calculation. Default: 'Y'. .PARAMETER LogToTable Ola internal logging to CommandLog table. Default: 'Y'. .PARAMETER OperatorName SQL Agent operator for email notification on failure. .PARAMETER Update Replace existing jobs with the same name. .PARAMETER ContinueOnError Continue with remaining jobs if one job fails. .PARAMETER UseExcludeTable When set, reads master.dbo.sqm_BackupExclude for active, non-orphaned entries and adds them as @ExcludeDatabases to the Ola DatabaseBackup command in the job step. If the table does not exist or is empty, the Databases parameter is used unchanged. .PARAMETER EnableException Throw exceptions immediately. .PARAMETER Confirm Request confirmation before creation. .PARAMETER WhatIf Shows what would happen without making changes. .EXAMPLE New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Full .EXAMPLE New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Full -Diff -Log .EXAMPLE # Create FULL job that automatically excludes databases from sqm_BackupExclude New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Full -UseExcludeTable .EXAMPLE # All three job types with exclude table integration New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Full -Diff -Log -UseExcludeTable -Update .EXAMPLE New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Full ` -FullScheduleTime "22:00" -FullScheduleDays @('Sunday') ` -OperatorName "DBAs" .EXAMPLE New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Log ` -LogScheduleTime "00:30" -LogScheduleDays @('EveryDay') ` -Databases "USER_DATABASES" .EXAMPLE New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Full -Diff -Log ` -FullScheduleDays @('Sunday') -FullScheduleTime "21:00" ` -DiffScheduleDays @('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday') ` -DiffScheduleTime "21:00" ` -LogScheduleDays @('EveryDay') -LogScheduleTime "00:00" ` -Update .EXAMPLE # LOG backup every 15 minutes, daily New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Log ` -LogScheduleDays @('EveryDay') -LogScheduleTime "00:00" ` -LogScheduleIntervalMinutes 15 -Update .EXAMPLE # FULL on multiple days, DIFF daily, LOG every 30 minutes New-sqmOlaUsrDbBackupJob -SqlInstance "SQL01" -Full -Diff -Log ` -FullScheduleDays @('Monday','Wednesday','Friday') -FullScheduleTime "22:00" ` -DiffScheduleDays @('EveryDay') -DiffScheduleTime "22:00" ` -LogScheduleDays @('EveryDay') -LogScheduleTime "00:00" ` -LogScheduleIntervalMinutes 30 -Update .NOTES Prerequisites: dbatools, Invoke-sqmLogging, Get-sqmConfig, Test-sqmOlaInstallation, Get-sqmSaLogin Configuration keys: OlaJobNameFull (Default: 'OlaHH-UserDatabases-FULL') OlaJobNameDiff (Default: 'OlaHH-UserDatabases-DIFF') OlaJobNameLog (Default: 'OlaHH-UserDatabases-LOG') Backup subdirectory: <BackupDirectory>\Usr-db #> function New-sqmOlaUsrDbBackupJob { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'None')] [OutputType([PSCustomObject[]])] param ( [Parameter(Mandatory = $false)] [string]$SqlInstance = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [System.Management.Automation.PSCredential]$SqlCredential, [Parameter(Mandatory = $false)] [string]$BackupDirectory, [Parameter(Mandatory = $false)] [string]$Databases = 'USER_DATABASES', # --- FULL --- [Parameter(Mandatory = $false)] [switch]$Full, [Parameter(Mandatory = $false)] [string]$FullJobName, [Parameter(Mandatory = $false)] [ValidatePattern('^\d{2}:\d{2}$')] [string]$FullScheduleTime = '20:00', [Parameter(Mandatory = $false)] [ValidateSet('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Weekdays', 'Weekend', 'EveryDay')] [string[]]$FullScheduleDays = @('Sunday'), [Parameter(Mandatory = $false)] [ValidateRange(0, 1440)] [int]$FullScheduleIntervalMinutes = 0, # --- DIFF --- [Parameter(Mandatory = $false)] [switch]$Diff, [Parameter(Mandatory = $false)] [string]$DiffJobName, [Parameter(Mandatory = $false)] [ValidatePattern('^\d{2}:\d{2}$')] [string]$DiffScheduleTime = '20:00', [Parameter(Mandatory = $false)] [ValidateSet('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Weekdays', 'Weekend', 'EveryDay')] [string[]]$DiffScheduleDays = @('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), [Parameter(Mandatory = $false)] [ValidateRange(0, 1440)] [int]$DiffScheduleIntervalMinutes = 0, # --- LOG --- [Parameter(Mandatory = $false)] [switch]$Log, [Parameter(Mandatory = $false)] [string]$LogJobName, [Parameter(Mandatory = $false)] [ValidatePattern('^\d{2}:\d{2}$')] [string]$LogScheduleTime = '00:00', [Parameter(Mandatory = $false)] [ValidateSet('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Weekdays', 'Weekend', 'EveryDay')] [string[]]$LogScheduleDays = @('EveryDay'), [Parameter(Mandatory = $false)] [ValidateRange(0, 1440)] [int]$LogScheduleIntervalMinutes = 0, # --- Allgemein --- [Parameter(Mandatory = $false)] [string]$JobCategory = 'Database Maintenance', [Parameter(Mandatory = $false)] [ValidateRange(0, 8760)] [int]$CleanupTime = 48, [Parameter(Mandatory = $false)] [ValidateSet('Y', 'N')] [string]$Compress = 'Y', [Parameter(Mandatory = $false)] [ValidateSet('Y', 'N')] [string]$Verify = 'Y', [Parameter(Mandatory = $false)] [ValidateSet('Y', 'N')] [string]$CheckSum = 'Y', [Parameter(Mandatory = $false)] [ValidateSet('Y', 'N')] [string]$LogToTable = 'Y', [Parameter(Mandatory = $false)] [string]$OperatorName, [Parameter(Mandatory = $false)] [switch]$Update, [Parameter(Mandatory = $false)] [switch]$ContinueOnError, [Parameter(Mandatory = $false)] [switch]$UseExcludeTable, [Parameter(Mandatory = $false)] [switch]$EnableException ) begin { $functionName = $MyInvocation.MyCommand.Name if (-not $script:dbatoolsAvailable) { $errMsg = "dbatools-Modul nicht gefunden." Invoke-sqmLogging -Message $errMsg -FunctionName $functionName -Level "ERROR" throw $errMsg } if (-not $Full -and -not $Diff -and -not $Log) { $errMsg = "Mindestens einer der Parameter -Full, -Diff oder -Log muss angegeben werden." Invoke-sqmLogging -Message $errMsg -FunctionName $functionName -Level "ERROR" throw $errMsg } $cfg = Get-sqmConfig # Job-Namen aus Konfiguration oder Default $effFullJobName = if ($FullJobName) { $FullJobName } elseif ($cfg['OlaJobNameFull']) { $cfg['OlaJobNameFull'] } else { 'OlaHH-UserDatabases-FULL' } $effDiffJobName = if ($DiffJobName) { $DiffJobName } elseif ($cfg['OlaJobNameDiff']) { $cfg['OlaJobNameDiff'] } else { 'OlaHH-UserDatabases-DIFF' } $effLogJobName = if ($LogJobName) { $LogJobName } elseif ($cfg['OlaJobNameLog']) { $cfg['OlaJobNameLog'] } else { 'OlaHH-UserDatabases-LOG' } $connParams = @{ SqlInstance = $SqlInstance } if ($SqlCredential) { $connParams['SqlCredential'] = $SqlCredential } $logDir = $cfg['LogPath'] if (-not $logDir) { $logDir = '$env:ProgramData\sqmSQLTool\Logs' } $maintenanceLogDir = Join-Path $logDir 'MaintenanceLog' $centralLogDir = $cfg['CentralPath'] $results = [System.Collections.Generic.List[PSCustomObject]]::new() } process { try { Invoke-sqmLogging -Message "Starte Erstellung der User-DB-Backup-Jobs auf $SqlInstance" -FunctionName $functionName -Level "INFO" # 1. Verbindung und Ola-Pruefung $sqlSrv = Connect-DbaInstance @connParams -ErrorAction Stop $olaCheck = Test-sqmOlaInstallation -SqlInstance $SqlInstance -SqlCredential $SqlCredential -RequiredSet Backup foreach ($w in $olaCheck.Warnings) { Invoke-sqmLogging -Message $w -FunctionName $functionName -Level "WARNING" } if (-not $olaCheck.IsInstalled) { throw $olaCheck.Message } if (-not $olaCheck.AgentRunning) { Invoke-sqmLogging -Message "SQL Agent ist nicht gestartet - Jobs koennen nicht ausgefuehrt werden." -FunctionName $functionName -Level "WARNING" } # 2. Backup-Verzeichnis ermitteln $effBackupDir = $BackupDirectory if (-not $effBackupDir) { try { $regQuery = "DECLARE @BackupDirectory NVARCHAR(4000); EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer', N'BackupDirectory', @BackupDirectory OUTPUT; SELECT @BackupDirectory AS BackupDirectory;" $regResult = Invoke-DbaQuery @connParams -Query $regQuery -ErrorAction Stop $effBackupDir = $regResult.BackupDirectory } catch { } if (-not $effBackupDir) { $effBackupDir = $sqlSrv.BackupDirectory } } if (-not $effBackupDir) { $effBackupDir = 'C:\Program Files\Microsoft SQL Server\MSSQL\Backup' } $usrBackupDir = "$effBackupDir\Usr-db" Invoke-sqmLogging -Message "Backup-Verzeichnis fuer User-Datenbanken: $usrBackupDir" -FunctionName $functionName -Level "INFO" # 3. SA-Login und Job-Kategorie $saLogin = Get-sqmSaLogin -SqlInstance $SqlInstance -SqlCredential $SqlCredential if (-not $saLogin) { $saLogin = 'sa' } $existingCat = Get-DbaAgentJobCategory @connParams -Category $JobCategory -ErrorAction SilentlyContinue if (-not $existingCat) { New-DbaAgentJobCategory @connParams -Category $JobCategory -ErrorAction SilentlyContinue | Out-Null } # 4. Jobs definieren $jobDefinitions = @() if ($Full) { $jobDefinitions += [PSCustomObject]@{ BackupType = 'FULL' JobName = $effFullJobName ScheduleTime = $FullScheduleTime ScheduleDays = $FullScheduleDays IntervalMinutes = $FullScheduleIntervalMinutes StepSuffix = 'FULL' } } if ($Diff) { $jobDefinitions += [PSCustomObject]@{ BackupType = 'DIFF' JobName = $effDiffJobName ScheduleTime = $DiffScheduleTime ScheduleDays = $DiffScheduleDays IntervalMinutes = $DiffScheduleIntervalMinutes StepSuffix = 'DIFF' } } if ($Log) { $jobDefinitions += [PSCustomObject]@{ BackupType = 'LOG' JobName = $effLogJobName ScheduleTime = $LogScheduleTime ScheduleDays = $LogScheduleDays IntervalMinutes = $LogScheduleIntervalMinutes StepSuffix = 'LOG' } } # 5. Hilfsfunktion: Wochentage in dbatools FrequencyInterval umrechnen # New-DbaAgentSchedule erwartet bei Weekly einen kombinierten Wochentag-String # oder die FrequencyInterval-Flags (Bitfeld: So=1, Mo=2, Di=4, Mi=8, Do=16, Fr=32, Sa=64) function ConvertTo-WeekdayInterval { param ([string[]]$Days) # Kurzformen aufloesen $expanded = foreach ($d in $Days) { switch ($d) { 'Weekdays' { 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' } 'Weekend' { 'Saturday', 'Sunday' } 'EveryDay' { 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' } default { $d } } } return ($expanded | Select-Object -Unique) } # 5b. Exclude-Tabelle auswerten wenn -UseExcludeTable gesetzt $excludeDatabasesParam = '' if ($UseExcludeTable) { Invoke-sqmLogging -Message "-UseExcludeTable gesetzt: Pruefe master.dbo.sqm_BackupExclude auf Ausnahmen." -FunctionName $functionName -Level "INFO" try { $excludeCheck = Invoke-DbaQuery @connParams -Database master ` -Query "SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'master.dbo.sqm_BackupExclude') AND type = 'U'" ` -ErrorAction Stop if ($excludeCheck) { $excludeRows = Invoke-DbaQuery @connParams -Database master ` -Query "SELECT DatabaseName FROM master.dbo.sqm_BackupExclude WHERE IsActive = 1 AND IsOrphaned = 0" ` -ErrorAction Stop if ($excludeRows) { $excludeList = ($excludeRows | Select-Object -ExpandProperty DatabaseName) -join ',' $excludeDatabasesParam = "@ExcludeDatabases = '$excludeList'," Invoke-sqmLogging -Message "sqm_BackupExclude: $($excludeRows.Count) Datenbank(en) werden aus den Jobs ausgeschlossen: $excludeList" -FunctionName $functionName -Level "INFO" } else { Invoke-sqmLogging -Message "sqm_BackupExclude enthaelt keine aktiven Eintraege. Parameter -Databases wird unveraendert verwendet." -FunctionName $functionName -Level "INFO" } } else { Invoke-sqmLogging -Message "Tabelle sqm_BackupExclude nicht gefunden. Parameter -Databases wird unveraendert verwendet." -FunctionName $functionName -Level "WARNING" } } catch { Invoke-sqmLogging -Message "Konnte sqm_BackupExclude nicht auslesen: $($_.Exception.Message). Parameter -Databases wird unveraendert verwendet." -FunctionName $functionName -Level "WARNING" } } # 6. Jeden Job anlegen $cleanupParam = if ($CleanupTime -gt 0) { "@CleanupTime = $CleanupTime," } else { '' } foreach ($jobDef in $jobDefinitions) { $result = [PSCustomObject]@{ SqlInstance = $SqlInstance BackupType = $jobDef.BackupType JobName = $jobDef.JobName BackupDirectory = $usrBackupDir Databases = $Databases ScheduleTime = $jobDef.ScheduleTime ScheduleDays = ($jobDef.ScheduleDays -join ', ') JobStatus = 'Unknown' OverallStatus = 'Unknown' Message = $null } try { # Vorhandenen Job behandeln $existingJob = Get-DbaAgentJob @connParams -Job $jobDef.JobName -ErrorAction SilentlyContinue if ($existingJob) { if (-not $Update) { $msg = "Job '$($jobDef.JobName)' existiert bereits. Verwenden Sie -Update zum ueberschreiben." Invoke-sqmLogging -Message $msg -FunctionName $functionName -Level "WARNING" $result.JobStatus = 'AlreadyExists' $result.OverallStatus = 'AlreadyExists' $result.Message = $msg $results.Add($result) if (-not $ContinueOnError) { continue } else { continue } } else { Remove-DbaAgentJob @connParams -Job $jobDef.JobName -Confirm:$false -ErrorAction SilentlyContinue | Out-Null Invoke-sqmLogging -Message "Vorhandener Job '$($jobDef.JobName)' wurde entfernt (Update)." -FunctionName $functionName -Level "INFO" } } # Ola-Kommando aufbauen $olaCommand = @" EXECUTE master.dbo.DatabaseBackup @Databases = '$Databases', $excludeDatabasesParam @Directory = N'$usrBackupDir', @BackupType = '$($jobDef.BackupType)', @Verify = '$Verify', $cleanupParam @Compress = '$Compress', @CheckSum = '$CheckSum', @LogToTable = '$LogToTable'; "@ $olaCommand = ($olaCommand -split "`n" | Where-Object { $_.Trim() -ne '' }) -join "`n" $timeParts = $jobDef.ScheduleTime -split ':' $startTime = '{0:D2}{1:D2}00' -f [int]$timeParts[0], [int]$timeParts[1] $outFile = "$("`$")(ESCAPE_SQUOTE(SQLLOGDIR))\MaintenanceLog\DatabaseBackup_USR_$($jobDef.StepSuffix)_$("`$")(ESCAPE_SQUOTE(STRTDT))_$("`$")(ESCAPE_SQUOTE(STRTTM)).txt" # WhatIf-Pruefung if (-not $PSCmdlet.ShouldProcess($SqlInstance, "Erstelle Job '$($jobDef.JobName)' [$($jobDef.BackupType)]")) { $result.JobStatus = 'WhatIf' $result.OverallStatus = 'WhatIf' $result.Message = "WhatIf: Job '$($jobDef.JobName)' wuerde erstellt werden." $results.Add($result) continue } # Job und Step anlegen New-DbaAgentJob @connParams ` -Job $jobDef.JobName ` -Category $JobCategory ` -OwnerLogin $saLogin ` -Description "Ola DatabaseBackup - $Databases - $($jobDef.BackupType) - $($jobDef.ScheduleDays -join '/') $($jobDef.ScheduleTime) - Ziel: $usrBackupDir" ` -EnableException -ErrorAction Stop | Out-Null New-DbaAgentJobStep @connParams ` -Job $jobDef.JobName ` -StepName "DatabaseBackup $($jobDef.StepSuffix)" ` -StepId 1 ` -Subsystem TransactSql ` -Command $olaCommand ` -OnSuccessAction QuitWithSuccess ` -OnFailAction QuitWithFailure ` -EnableException -ErrorAction Stop | Out-Null # OutputFileName setzen try { $srv2 = Connect-DbaInstance @connParams -ErrorAction Stop $agJob = $srv2.JobServer.Jobs[$jobDef.JobName] $step = $agJob.JobSteps | Where-Object { $_.ID -eq 1 } if ($step) { $step.OutputFileName = $outFile $step.AppendToLog = $true $step.Alter() } } catch { Invoke-sqmLogging -Message "OutputFileName fuer Job '$($jobDef.JobName)' konnte nicht gesetzt werden: $($_.Exception.Message)" -FunctionName $functionName -Level "VERBOSE" } # Zeitplan anlegen $expandedDays = ConvertTo-WeekdayInterval -Days $jobDef.ScheduleDays $intervalSuffix = if ($jobDef.IntervalMinutes -gt 0) { "_every$($jobDef.IntervalMinutes)min" } else { '' } $scheduleName = "MSSQLTools_UsrDbBackup_$($jobDef.StepSuffix)_$($jobDef.ScheduleTime -replace ':', '')$intervalSuffix" $schedParams = @{ SqlInstance = $SqlInstance Job = $jobDef.JobName Schedule = $scheduleName Force = $true FrequencyType = 'Weekly' FrequencyInterval = $expandedDays StartTime = $startTime } if ($SqlCredential) { $schedParams.SqlCredential = $SqlCredential } if ($jobDef.IntervalMinutes -gt 0) { # Wiederholt sich innerhalb des Tages alle N Minuten bis Mitternacht $schedParams['FrequencySubDayType'] = 'Minutes' $schedParams['FrequencySubDayInterval'] = $jobDef.IntervalMinutes $schedParams['EndTime'] = '235959' Invoke-sqmLogging -Message "Schedule '$scheduleName': woechentlich $($expandedDays -join '/'), Start $($jobDef.ScheduleTime), alle $($jobDef.IntervalMinutes) Minuten bis 23:59." -FunctionName $functionName -Level "INFO" } else { Invoke-sqmLogging -Message "Schedule '$scheduleName': woechentlich $($expandedDays -join '/') um $($jobDef.ScheduleTime)." -FunctionName $functionName -Level "INFO" } New-DbaAgentSchedule @schedParams | Out-Null # Operator if ($OperatorName) { $op = Get-DbaAgentOperator @connParams -Operator $OperatorName -ErrorAction SilentlyContinue if ($op) { Set-DbaAgentJob @connParams -Job $jobDef.JobName -OperatorToEmail $OperatorName -EmailLevel OnFailure -ErrorAction SilentlyContinue | Out-Null } else { Invoke-sqmLogging -Message "Operator '$OperatorName' nicht gefunden." -FunctionName $functionName -Level "WARNING" } } $result.JobStatus = 'Created' $result.OverallStatus = 'Success' $intervalInfo = if ($jobDef.IntervalMinutes -gt 0) { ", alle $($jobDef.IntervalMinutes) Min." } else { '' } $result.Message = "Job '$($jobDef.JobName)' erstellt. $($expandedDays -join '/') $($jobDef.ScheduleTime)$intervalInfo -> $usrBackupDir" Invoke-sqmLogging -Message $result.Message -FunctionName $functionName -Level "INFO" } catch { $errMsg = $_.Exception.Message Invoke-sqmLogging -Message "Fehler bei Job '$($jobDef.JobName)': $errMsg" -FunctionName $functionName -Level "ERROR" $result.JobStatus = 'Failed' $result.OverallStatus = 'Failed' $result.Message = $errMsg if ($EnableException) { throw } if (-not $ContinueOnError) { $results.Add($result); throw } } $results.Add($result) } # 7. Konfigurationsbericht schreiben if (-not (Test-Path $maintenanceLogDir)) { New-Item -ItemType Directory -Path $maintenanceLogDir -Force | Out-Null } $safeInst = $SqlInstance -replace '[\\/:*?"<>|]', '_' $datestamp = Get-Date -Format 'yyyy-MM-dd' $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' $logFile = Join-Path $maintenanceLogDir "OlaUsrBackup_${safeInst}_${datestamp}.txt" $reportLines = @( "# ================================================================" "# MSSQLTools - Ola User-DB Backup Jobs Konfigurationsbericht" "# Instanz : $SqlInstance" "# Erstellt : $timestamp" "# Backup-Verz. : $usrBackupDir" "# Datenbanken : $Databases" "# Cleanup (h) : $CleanupTime" "# Compress : $Compress | Verify: $Verify | CheckSum: $CheckSum" "# ----------------------------------------------------------------" ) foreach ($r in $results) { $reportLines += "# [$($r.BackupType)] $($r.JobName) | $($r.ScheduleDays) $($r.ScheduleTime) | Status: $($r.JobStatus)" } $reportLines += "# ================================================================" $reportLines | Out-File -FilePath $logFile -Encoding UTF8 -Force if ($centralLogDir) { $centralSub = Join-Path $centralLogDir 'MaintenanceLog' if (-not (Test-Path $centralSub)) { New-Item -ItemType Directory -Path $centralSub -Force | Out-Null } Copy-Item $logFile (Join-Path $centralSub (Split-Path $logFile -Leaf)) -Force -ErrorAction SilentlyContinue } } catch { $errMsg = $_.Exception.Message Invoke-sqmLogging -Message "Schwerwiegender Fehler: $errMsg" -FunctionName $functionName -Level "ERROR" if ($EnableException) { throw } if (-not $ContinueOnError) { throw } } return $results.ToArray() } } |