Os logs de eventos são uma das fontes mais ricas de informação sobre o comportamento do sistema operacional Windows, aplicações e serviços. Eles registram desde erros críticos até eventos informativos, sendo essenciais para diagnóstico, monitoramento e auditoria. Nesta aula, você aprenderá a acessar e manipular esses logs usando o PowerShell, que oferece cmdlets poderosos e flexíveis para consulta e análise.

Dominar a leitura de logs de eventos é uma habilidade fundamental para qualquer administrador de sistemas ou profissional de segurança. Com o PowerShell, você pode automatizar a coleta de informações, gerar relatórios e reagir proativamente a problemas antes que eles se tornem críticos. Vamos explorar os dois principais cmdlets: Get-EventLog (mais antigo, porém ainda útil) e Get-WinEvent (moderno e recomendado).

Get-EventLog e Get-WinEvent

O cmdlet Get-EventLog foi introduzido nas primeiras versões do PowerShell e é compatível com versões antigas do Windows. Ele lê logs clássicos, como Application, System e Security, e oferece uma sintaxe simples. No entanto, ele não suporta logs criados pelo Windows Event Log (WEL) moderno, como os logs do PowerShell ou do Active Directory. Por isso, é recomendado usar Get-WinEvent, que é mais poderoso e flexível, capaz de acessar todos os logs de eventos, incluindo os personalizados.

Vamos começar com exemplos básicos de cada cmdlet. O Get-EventLog requer o nome do log e pode ser filtrado por entrada. Já o Get-WinEvent aceita parâmetros como -LogName e -FilterXPath para consultas avançadas. Veja como usá-los:

# Exemplo com Get-EventLog
Get-EventLog -LogName System -Newest 10

# Exemplo com Get-WinEvent
Get-WinEvent -LogName System -MaxEvents 10

Perceba que Get-WinEvent é mais eficiente e retorna objetos com propriedades enriquecidas. Além disso, ele permite consultas complexas usando XML Path Language (XPath), que veremos na seção de filtragem. Sempre prefira Get-WinEvent em scripts novos, a menos que precise de compatibilidade com sistemas legados.

Filtragem

Filtrar eventos é crucial para encontrar rapidamente o que interessa sem processar milhares de registros. O PowerShell oferece várias maneiras de filtrar: usando o parâmetro -FilterXPath (para Get-WinEvent), -FilterHashtable (também no Get-WinEvent), ou filtrando após a coleta com Where-Object. A abordagem mais eficiente é usar o filtro no nível do provedor, reduzindo a quantidade de dados transferidos.

O -FilterHashtable é uma sintaxe amigável para consultas comuns, como filtrar por nível de severidade, data ou ID do evento. Veja exemplos:

# Filtrar por nível (Erro e Crítico) no log System
Get-WinEvent -FilterHashtable @{LogName='System'; Level=1,2} -MaxEvents 20

# Filtrar por data (últimas 24 horas)
$desde = (Get-Date).AddDays(-1)
Get-WinEvent -FilterHashtable @{LogName='Security'; StartTime=$desde} -MaxEvents 50

# Filtrar por ID do evento e provedor
Get-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='.NET Runtime'; Id=1026} -MaxEvents 5

Para consultas mais complexas, use -FilterXPath. Ele permite combinar condições com operadores lógicos e consultar campos específicos do XML do evento. Por exemplo, para buscar eventos de erro no log System com ID 1000 e 1001:

$xpath = "*[System[(EventID=1000 or EventID=1001) and Level=2]]"
Get-WinEvent -LogName System -FilterXPath $xpath -MaxEvents 10

Nota: O XPath é poderoso, mas exige conhecimento da estrutura do XML dos eventos. Para a maioria dos casos, -FilterHashtable é suficiente e mais legível.

Análise

Depois de coletar os eventos, a análise envolve extrair informações úteis, agrupar dados, identificar padrões e gerar relatórios. O PowerShell facilita isso com cmdlets como Group-Object, Measure-Object e Select-Object. Vamos explorar algumas técnicas comuns.

Primeiro, vamos contar eventos por nível de severidade:

$eventos = Get-WinEvent -LogName System -MaxEvents 1000
$eventos | Group-Object LevelDisplayName | Select-Object Name, Count

Isso retorna uma tabela mostrando quantos eventos de cada nível existem. Para analisar eventos de erro específicos, podemos agrupar por ID:

$eventos | Where-Object LevelDisplayName -eq 'Erro' | Group-Object Id | Sort-Object Count -Descending | Select-Object -First 10 Name, Count

Outra análise útil é identificar a origem dos eventos (provedores) e os horários de pico. Podemos também exportar os dados para CSV ou JSON para gerar relatórios em ferramentas externas:

$eventos | Export-Csv -Path "C:\Temp\eventos.csv" -NoTypeInformation
Get-WinEvent -LogName Security -MaxEvents 100 | ConvertTo-Json | Out-File -FilePath "C:\Temp\security.json"

Além disso, o PowerShell permite criar alertas automatizados. Por exemplo, você pode verificar se há eventos críticos recentes e enviar um e-mail ou registrar em um arquivo. Isso será abordado na seção de casos de uso.

Casos de uso

Os logs de eventos têm inúmeras aplicações práticas. Um dos usos mais comuns é o monitoramento de falhas de aplicativos. Por exemplo, se um aplicativo está gerando erros repetidamente, você pode identificar o ID do evento e o provedor para diagnosticar o problema. Outro caso é a auditoria de segurança, onde você pode rastrear tentativas de login falhas ou alterações em políticas.

Vamos ver um exemplo de monitoramento de falhas de disco. O log System contém eventos do driver de disco com IDs como 7 (erro de disco) e 51 (erro de paginação). Podemos criar um script que verifica se esses eventos ocorreram na última hora:

$inicio = (Get-Date).AddHours(-1)
$errosDisco = Get-WinEvent -FilterHashtable @{LogName='System'; StartTime=$inicio; Id=7,51} -ErrorAction SilentlyContinue
if ($errosDisco) {
    Write-Host "Atenção: Erros de disco detectados!" -ForegroundColor Red
    $errosDisco | Format-Table TimeCreated, Id, Message -Wrap
} else {
    Write-Host "Nenhum erro de disco na última hora."
}

Outro caso é o monitoramento de segurança. Para detectar tentativas de login falhas, você pode consultar o log Security com o ID 4625 (falha de logon). Veja como listar as últimas 10 falhas:

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 10 |
    Select-Object TimeCreated, @{n='Usuário';e={$_.Properties[5].Value}}, @{n='Origem';e={$_.Properties[13].Value}} | Format-Table -AutoSize

Por fim, podemos criar um relatório diário de eventos críticos e enviar por e-mail. Isso ajuda a manter um histórico e a reagir rapidamente. O script pode ser agendado usando o Task Scheduler.

Boas práticas e observações finais

Ao trabalhar com logs de eventos, é importante considerar a performance. Consultar logs grandes sem filtros pode ser lento e consumir muita memória. Sempre use -MaxEvents ou filtros para limitar o escopo. Além disso, evite usar Where-Object em coleções enormes; prefira filtros no nível do provedor.

Outra boa prática é tratar erros ao consultar logs que podem não existir ou exigir privilégios elevados. Use -ErrorAction SilentlyContinue ou valide com Get-WinEvent -ListLog * para ver os logs disponíveis. Lembre-se de que alguns logs só podem ser lidos por administradores.

Por fim, sempre documente seus scripts e mantenha-os modulares. Os logs de eventos são uma ferramenta poderosa, e o PowerShell é o aliado perfeito para extrair valor deles.

Referências

Exercícios

  1. Use Get-WinEvent para listar os últimos 20 eventos do log System, mostrando apenas TimeCreated, Id e ProviderName. Salve o resultado em uma variável e exiba em formato de tabela.
  2. ✓ Resposta:
    $eventos = Get-WinEvent -LogName System -MaxEvents 20
    $eventos | Select-Object TimeCreated, Id, ProviderName | Format-Table -AutoSize
  3. Filtre eventos do log Application com nível de erro (Level=2) e ID 1000, usando -FilterHashtable. Limite a 5 eventos e exiba o primeiro evento como lista.
  4. ✓ Resposta:
    $eventos = Get-WinEvent -FilterHashtable @{LogName='Application'; Level=2; Id=1000} -MaxEvents 5
    $eventos[0] | Format-List *
  5. Conte quantos eventos de erro (Level=2) existem no log System nas últimas 24 horas. Exiba o resultado.
  6. ✓ Resposta:
    $desde = (Get-Date).AddDays(-1)
    $erros = Get-WinEvent -FilterHashtable @{LogName='System'; Level=2; StartTime=$desde}
    $erros.Count
  7. Escreva um script que verifique se houve eventos de segurança com ID 4625 (falha de logon) na última hora e, se houver, exiba uma mensagem de alerta com a quantidade.
  8. ✓ Resposta:
    $inicio = (Get-Date).AddHours(-1)
    $falhas = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=$inicio} -ErrorAction SilentlyContinue
    if ($falhas) {
        Write-Host "ALERTA: $($falhas.Count) tentativas de logon falhas na última hora!" -ForegroundColor Red
    } else {
        Write-Host "Nenhuma tentativa de logon falha na última hora."
    }
  9. Exporte os últimos 50 eventos do log System para um arquivo CSV chamado "eventos_system.csv" no diretório atual.
  10. ✓ Resposta:
    Get-WinEvent -LogName System -MaxEvents 50 | Export-Csv -Path ".\eventos_system.csv" -NoTypeInformation