Monitorando eventos do sistema com PowerShell e Event Log
1. Introdução ao Windows Event Log e PowerShell
O Windows Event Log é o sistema centralizado de registro de eventos do sistema operacional, organizado em logs principais como System (eventos do sistema e drivers), Security (logons, auditorias) e Application (eventos de aplicativos). Cada evento contém metadados críticos: ID único, nível (Erro, Aviso, Informação, Crítico), timestamp, origem e mensagem descritiva.
O PowerShell se destaca para consultar e monitorar esses logs por três razões fundamentais:
- Cmdlets nativos como Get-WinEvent e Get-EventLog oferecem acesso direto e rápido
- Filtros avançados permitem consultas complexas sem carregar todo o log na memória
- Automação possibilita criar scripts de monitoramento contínuo com notificações em tempo real
Enquanto Get-EventLog é mais simples e compatível com versões antigas, Get-WinEvent é o cmdlet moderno recomendado, com suporte a XPath e melhor desempenho em logs grandes.
2. Consultando logs com Get-WinEvent
A sintaxe básica do Get-WinEvent é direta:
# Listar todos os logs disponíveis
Get-WinEvent -ListLog *
# Consultar os 10 eventos mais recentes do log System
Get-WinEvent -LogName System -MaxEvents 10
# Filtrar por nível (2=Erro, 3=Aviso, 4=Informação)
Get-WinEvent -LogName System -MaxEvents 5 | Where-Object {$_.LevelDisplayName -eq "Error"}
Para consultas mais precisas, use filtros XPath:
# Eventos de erro com ID específico (41 = desligamento inesperado)
$xmlFilter = @"
<QueryList>
<Query Id="0">
<Select Path="System">
*[System[(EventID=41) and (Level=2)]]
</Select>
</Query>
</QueryList>
"@
Get-WinEvent -FilterXml $xmlFilter -MaxEvents 10
Exemplos práticos adicionais:
# Últimos 50 eventos de logon (ID 4624) no Security
Get-WinEvent -LogName Security -MaxEvents 50 | Where-Object {$_.Id -eq 4624}
# Falhas de disco (ID 7, 11, 15) no System
$diskIDs = 7,11,15
Get-WinEvent -LogName System | Where-Object {$diskIDs -contains $_.Id -and $_.LevelDisplayName -eq "Error"}
3. Filtrando eventos por data, nível e origem
O PowerShell permite filtrar eventos por janelas de tempo com objetos [datetime]:
# Eventos das últimas 24 horas
$startDate = (Get-Date).AddHours(-24)
Get-WinEvent -LogName System | Where-Object {$_.TimeCreated -ge $startDate}
# Eventos entre datas específicas
$start = Get-Date "2025-01-01"
$end = Get-Date "2025-01-15"
Get-WinEvent -LogName Security -MaxEvents 100 | Where-Object {
$_.TimeCreated -ge $start -and $_.TimeCreated -le $end
}
Filtragem por nível e origem:
# Eventos críticos (Level 1) de qualquer log
Get-WinEvent -FilterHashtable @{LogName='System','Application'; Level=1}
# Eventos de uma origem específica (ex: Service Control Manager)
Get-WinEvent -LogName System | Where-Object {$_.ProviderName -eq "Service Control Manager"}
# Combinando múltiplos critérios
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4624,4625
StartTime=(Get-Date).AddDays(-7)
}
4. Exportando e salvando resultados de eventos
Para análises posteriores ou compartilhamento, exporte os resultados:
# Exportar para CSV
Get-WinEvent -LogName System -MaxEvents 100 |
Select-Object TimeCreated, Id, LevelDisplayName, Message |
Export-Csv -Path "C:\Logs\eventos_sistema.csv" -NoTypeInformation
# Exportar para HTML com formatação
Get-WinEvent -LogName System -MaxEvents 50 |
Select-Object TimeCreated, Id, LevelDisplayName, Message |
ConvertTo-Html -Title "Eventos do Sistema" |
Out-File "C:\Logs\eventos.html"
# Exportar para XML (preserva todos os campos)
Get-WinEvent -LogName System -MaxEvents 10 | Export-Clixml -Path "C:\Logs\eventos.xml"
Para grandes volumes, use paginação e evite carregar tudo na memória:
# Processamento em lotes de 1000 eventos
$batchSize = 1000
$totalProcessed = 0
Get-WinEvent -LogName System -Oldest | ForEach-Object {
$_ | Export-Csv -Path "C:\Logs\batch_$totalProcessed.csv" -Append
$totalProcessed++
if ($totalProcessed % $batchSize -eq 0) {
Write-Host "Processados $totalProcessed eventos..."
}
}
5. Monitoramento contínuo com loops e eventos em tempo real
Para monitoramento em tempo real, use Register-ObjectEvent com o System.Diagnostics.Eventing.Reader.EventLogWatcher:
# Monitorar novos eventos de erro no System
$logWatcher = New-Object System.Diagnostics.Eventing.Reader.EventLogWatcher(
New-Object System.Diagnostics.Eventing.Reader.EventLogQuery("System", [System.Diagnostics.Eventing.Reader.PathType]::LogName, "*[System[(Level=2)]]")
)
Register-ObjectEvent -InputObject $logWatcher -EventName "EventRecordWritten" -Action {
$event = $EventArgs.EventRecord
Write-Host "[$(Get-Date)] NOVO EVENTO: ID=$($event.Id) - $($event.LevelDisplayName)"
Write-Host "Mensagem: $($event.FormatDescription())"
Write-Host "---"
}
$logWatcher.Enabled = $true
Write-Host "Monitoramento iniciado. Pressione Ctrl+C para parar."
Wait-Event
Alternativa com loop simples:
# Loop de verificação a cada 30 segundos
$lastCheck = (Get-Date).AddMinutes(-5)
while ($true) {
$newEvents = Get-WinEvent -LogName System |
Where-Object {$_.TimeCreated -gt $lastCheck -and $_.LevelDisplayName -eq "Error"}
foreach ($event in $newEvents) {
Write-Host "[ALERTA] Evento ID $($event.Id) em $($event.TimeCreated)"
}
$lastCheck = Get-Date
Start-Sleep -Seconds 30
}
6. Automatizando notificações e ações com base em eventos
Combinando monitoramento com ações automáticas:
# Script de notificação por e-mail para eventos críticos
$emailParams = @{
From = "monitor@empresa.com"
To = "admin@empresa.com"
Subject = "[ALERTA CRÍTICO] Evento detectado"
SmtpServer = "smtp.empresa.com"
}
# Monitorar e reagir a eventos específicos
$action = {
$event = $EventArgs.EventRecord
if ($event.Id -eq 41 -or $event.Id -eq 6008) {
# Desligamento inesperado - reiniciar serviço crítico
Restart-Service -Name "Spooler" -Force
# Enviar alerta
$body = "Evento crítico detectado:`nID: $($event.Id)`nData: $($event.TimeCreated)`nLog: $($event.LogName)"
Send-MailMessage @emailParams -Body $body
}
}
# Aplicar o watcher com a ação
$query = New-Object System.Diagnostics.Eventing.Reader.EventLogQuery("System", [System.Diagnostics.Eventing.Reader.PathType]::LogName, "*[System[(Level=1 or Level=2)]]")
$watcher = New-Object System.Diagnostics.Eventing.Reader.EventLogWatcher($query)
Register-ObjectEvent -InputObject $watcher -EventName "EventRecordWritten" -Action $action
$watcher.Enabled = $true
7. Boas práticas e considerações de segurança
Permissões necessárias:
- Para logs padrão (System, Application): geralmente acesso de leitura para todos os usuários
- Para Security log: privilégios de administrador ou SeSecurityPrivilege
- Execute scripts como SYSTEM ou conta de serviço dedicada
Cuidados com performance:
- Sempre use -MaxEvents ou filtros XPath para evitar carregar logs completos
- Em loops infinitos, inclua Start-Sleep para evitar 100% de CPU
- Monitore o consumo de memória com Get-Process -Id $pid
Estratégias de rotação:
# Verificar tamanho do log e forçar rotação se necessário
$log = Get-WinEvent -ListLog System
if ($log.FileSize -gt 100MB) {
# Backup antes de limpar
Get-WinEvent -LogName System -Oldest | Export-Csv "C:\Backup\system_$(Get-Date -Format yyyyMMdd).csv"
# Limpar log (requer admin)
Clear-EventLog -LogName System
}
8. Exemplo completo: script de monitoramento em produção
<#
.SYNOPSIS
Monitor de eventos do sistema com notificação e ação automática
.DESCRIPTION
Monitora logs do Windows e executa ações baseadas em regras configuráveis
.PARAMETER LogName
Nome do log a monitorar (System, Security, Application)
.PARAMETER CriticalIDs
Array de IDs de eventos considerados críticos
.PARAMETER AlertEmail
Endereço de e-mail para notificações
#>
param(
[string]$LogName = "System",
[int[]]$CriticalIDs = @(41, 6008, 1001),
[string]$AlertEmail = "admin@empresa.com"
)
function Send-EventAlert {
param($Event)
$body = @"
ALERTA DE EVENTO CRÍTICO
Log: $($Event.LogName)
ID: $($Event.Id)
Data: $($Event.TimeCreated)
Nível: $($Event.LevelDisplayName)
Mensagem: $($Event.FormatDescription())
"@
Send-MailMessage -From "monitor@empresa.com" -To $AlertEmail `
-Subject "[CRÍTICO] Evento ID $($Event.Id) em $($Event.TimeCreated)" `
-Body $body -SmtpServer "smtp.empresa.com"
}
function Invoke-Remediation {
param($Event)
switch ($Event.Id) {
41 { Restart-Service -Name "Spooler" -Force -ErrorAction SilentlyContinue }
6008 { Write-EventLog -LogName Application -Source "Monitor" -EntryType Warning `
-EventId 999 -Message "Sistema reiniciou inesperadamente" }
default { Write-Host "Nenhuma ação definida para ID $($Event.Id)" }
}
}
# Configuração do watcher
$queryXml = @"
<QueryList>
<Query Id="0">
<Select Path="$LogName">
*[System[($(($CriticalIDs | ForEach-Object {"EventID=$_"}) -join " or "))]]
</Select>
</Query>
</QueryList>
"@
$watcher = New-Object System.Diagnostics.Eventing.Reader.EventLogWatcher(
[System.Diagnostics.Eventing.Reader.EventLogQuery]::new($LogName, [System.Diagnostics.Eventing.Reader.PathType]::LogName, $queryXml)
)
$action = {
$event = $EventArgs.EventRecord
Write-Host "[$(Get-Date)] Evento crítico detectado: ID $($event.Id)"
Send-EventAlert -Event $event
Invoke-Remediation -Event $event
}
Register-ObjectEvent -InputObject $watcher -EventName "EventRecordWritten" -Action $action
$watcher.Enabled = $true
Write-Host "Monitor iniciado em $LogName para IDs: $($CriticalIDs -join ', ')"
Write-Host "Pressione Ctrl+C para parar."
Wait-Event
Para testar o script, gere eventos de teste:
# Simular evento crítico (requer admin)
Write-EventLog -LogName System -Source "EventLog" -EntryType Error -EventId 41 -Message "Teste de monitoramento"
Referências
- Get-WinEvent (Microsoft Documentation) — Documentação oficial do cmdlet principal para consulta de eventos no Windows.
- Windows Event Log (Microsoft Learn) — Visão completa do sistema de logs do Windows, incluindo estrutura e APIs.
- PowerShell Event Log Monitoring Scripts (PowerShell.org) — Tutorial prático com exemplos de scripts de monitoramento em tempo real.
- Export-Csv and ConvertTo-Html (SS64.com) — Referência rápida para exportação de dados do PowerShell em diferentes formatos.
- Register-ObjectEvent (Microsoft Documentation) — Documentação oficial para registro de eventos assíncronos no PowerShell.
- Windows Event IDs Reference (Ultimate Windows Security) — Catálogo completo de IDs de eventos do Windows com descrições detalhadas.
- Best Practices for PowerShell Scripting (Microsoft) — Guia de boas práticas para scripts PowerShell em produção.