<# .SYNOPSIS Instaleaza monitorizarea UPS pe serverul Oracle de productie: copiaza scriptul, scrie config.json, restrictioneaza drepturile si inregistreaza taskul programat. .DESCRIPTION Se ruleaza PE SERVER, dintr-un PowerShell ridicat (Administrator). Taskul ruleaza ca NT AUTHORITY\SYSTEM - cont care e deja membru ORA_DBA pe acest server, deci "sqlplus / as sysdba" merge fara parola. Doua detalii care fac diferenta si sunt usor de ratat: - AllowStartIfOnBatteries + DontStopIfGoingOnBatteries: fara ele, Windows opreste taskul exact cand serverul trece pe baterie, adica exact cand ai nevoie de el; - al doilea declansator, care repeta la 10 minute cu MultipleInstances=IgnoreNew: daca procesul moare, revine singur; daca traieste, pornirea e ignorata. .PARAMETER SmtpPassword Parola contului SMTP. Ajunge in config.json, care primeste ACL doar pentru SYSTEM si Administratori. NU se comiteaza in git. .PARAMETER Uninstall Sterge taskul programat. Nu sterge directorul, logurile sau configuratia. .EXAMPLE powershell -ExecutionPolicy Bypass -File .\install-ups-monitor.ps1 -SmtpPassword '...' #> [CmdletBinding()] param( [string]$InstallDir = 'C:\ROMFAST\ups-monitor', [string]$SmtpServer = 'mail.romfast.ro', [int]$SmtpPort = 587, [string]$SmtpUser = 'ups@romfast.ro', [string]$SmtpFrom = 'ups@romfast.ro', [string]$SmtpPassword, [string[]]$MailTo = @('marius.mutu@romfast.ro'), [int]$PollSeconds = 15, [int]$ShutdownAfterMinutesOnBattery = 10, [int]$ShutdownAtBatteryPercent = 35, [string]$OracleHome = 'C:\Users\Administrator\Downloads\WINDOWS.X64_193000_db_home', [string]$OracleSid = 'ROA', [string]$OracleService = 'OracleServiceROA', [string]$OracleListenerService = 'OracleOraDB19Home1TNSListener', [int]$OracleShutdownTimeoutSeconds = 180, [switch]$Uninstall ) Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' $TaskName = 'ROMFAST UPS Monitor' $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($identity) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Scriptul trebuie rulat dintr-un PowerShell ridicat (Administrator).' } if ($Uninstall) { if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false Write-Host "Task '$TaskName' sters. Directorul $InstallDir a ramas pe loc." } else { Write-Host "Taskul '$TaskName' nu era inregistrat." } return } if (-not $SmtpPassword) { throw 'Lipseste -SmtpPassword. Fara el nu pleaca nicio alerta.' } # --- fisiere --------------------------------------------------------------- $logDir = Join-Path $InstallDir 'log' foreach ($d in @($InstallDir, $logDir)) { if (-not (Test-Path -LiteralPath $d)) { New-Item -ItemType Directory -Path $d -Force | Out-Null } } $sourceScript = Join-Path $PSScriptRoot 'ups-monitor.ps1' if (-not (Test-Path -LiteralPath $sourceScript)) { throw "Nu gasesc ups-monitor.ps1 langa install-ups-monitor.ps1 ($sourceScript)" } Copy-Item -LiteralPath $sourceScript -Destination $InstallDir -Force Write-Host "Copiat ups-monitor.ps1 in $InstallDir" $config = [ordered]@{ enabled = $true pollSeconds = $PollSeconds shutdownAfterMinutesOnBattery = $ShutdownAfterMinutesOnBattery shutdownAtBatteryPercent = $ShutdownAtBatteryPercent shutdownAtRuntimeSeconds = 0 confirmPolls = 3 commsLostPolls = 8 commsAlertRepeatHours = 24 logPath = $logDir stateFile = (Join-Path $InstallDir 'state.json') mailTo = $MailTo smtp = [ordered]@{ server = $SmtpServer port = $SmtpPort user = $SmtpUser password = $SmtpPassword from = $SmtpFrom } oracle = [ordered]@{ home = $OracleHome sid = $OracleSid service = $OracleService listenerService = $OracleListenerService shutdownTimeoutSeconds = $OracleShutdownTimeoutSeconds } } $configPath = Join-Path $InstallDir 'config.json' $config | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $configPath -Encoding UTF8 Write-Host "Scris $configPath" # --- drepturi: config.json contine parola SMTP ------------------------------ $acl = Get-Acl -LiteralPath $InstallDir $acl.SetAccessRuleProtection($true, $false) # taie mostenirea, fara sa copieze regulile foreach ($r in @($acl.Access)) { $acl.RemoveAccessRule($r) | Out-Null } foreach ($who in @('NT AUTHORITY\SYSTEM', 'BUILTIN\Administrators')) { $acl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule( $who, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow'))) } Set-Acl -LiteralPath $InstallDir -AclObject $acl Write-Host "Drepturi restranse pe $InstallDir : doar SYSTEM si Administratori" # --- verificari inainte de inregistrare ------------------------------------- foreach ($svc in @($OracleService, $OracleListenerService)) { if (-not (Get-Service -Name $svc -ErrorAction SilentlyContinue)) { Write-Warning "Serviciul '$svc' nu exista pe acest server - verifica parametrii Oracle." } } if (-not (Test-Path -LiteralPath (Join-Path $OracleHome 'bin\sqlplus.exe'))) { Write-Warning "sqlplus.exe nu e la $OracleHome\bin - oprirea va cadea pe Stop-Service." } # --- taskul programat ------------------------------------------------------- $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ( '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File "{0}\ups-monitor.ps1" -Mode Run' -f $InstallDir) $triggerBoot = New-ScheduledTaskTrigger -AtStartup # Al doilea declansator: reporneste procesul daca a murit, fara sa-l dubleze. # -RepetitionDuration se lasa nespecificat intentionat: inseamna "la nesfarsit". # [TimeSpan]::MaxValue, desi documentat pentru asta, e respins de Task Scheduler # ("P99999999DT23H59M59S ... out of range"). $triggerRepeat = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) ` -RepetitionInterval (New-TimeSpan -Minutes 10) $settings = New-ScheduledTaskSettingsSet ` -AllowStartIfOnBatteries ` -DontStopIfGoingOnBatteries ` -StartWhenAvailable ` -MultipleInstances IgnoreNew ` -ExecutionTimeLimit ([TimeSpan]::Zero) ` -RestartCount 999 ` -RestartInterval (New-TimeSpan -Minutes 1) $taskPrincipal = New-ScheduledTaskPrincipal -UserId 'NT AUTHORITY\SYSTEM' -LogonType ServiceAccount -RunLevel Highest if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false } Register-ScheduledTask -TaskName $TaskName ` -Description 'Monitorizeaza UPS-ul prin canalul HID nativ, alerteaza pe email si opreste curat Oracle inainte de epuizarea bateriei. Inlocuieste ViewPower.' ` -Action $action -Trigger @($triggerBoot, $triggerRepeat) ` -Settings $settings -Principal $taskPrincipal | Out-Null Start-ScheduledTask -TaskName $TaskName Start-Sleep -Seconds 5 Write-Host '' Write-Host '--- rezultat ---' Get-ScheduledTask -TaskName $TaskName | Format-Table -AutoSize TaskName, State Get-ScheduledTaskInfo -TaskName $TaskName | Format-List LastRunTime, LastTaskResult, NumberOfMissedRuns Write-Host '' Write-Host 'Verificari utile:' Write-Host (" powershell -ExecutionPolicy Bypass -File {0}\ups-monitor.ps1 -Mode Status" -f $InstallDir) Write-Host (" powershell -ExecutionPolicy Bypass -File {0}\ups-monitor.ps1 -Mode TestMail" -f $InstallDir) Write-Host (" powershell -ExecutionPolicy Bypass -File {0}\ups-monitor.ps1 -Mode TestShutdown" -f $InstallDir) Write-Host '' Write-Host ("Oprire de urgenta a automatismului: New-Item -ItemType File '{0}\DEZACTIVAT'" -f $InstallDir)