Bem-vindo à aula 77 do nosso curso de PowerShell! Hoje vamos explorar um dos usos mais poderosos do PowerShell: a criação de scripts de monitoramento. Monitorar sistemas é uma tarefa crucial para garantir disponibilidade, desempenho e segurança. Com PowerShell, você pode automatizar a verificação de serviços, recursos do sistema, gerar alertas e manter logs detalhados, tudo de forma eficiente e integrada ao ecossistema Windows.

Nesta aula, vamos construir desde a base: primeiro, aprenderemos a verificar o estado de serviços e recursos do sistema. Depois, veremos como transformar essas verificações em alertas úteis, seja por e-mail, log ou até mesmo pop-ups. Em seguida, abordaremos a importância do logging e como implementar um sistema de registro robusto. Por fim, discutiremos como agendar a execução periódica dos nossos scripts, seja com o Agendador de Tarefas ou usando loops internos. Ao final, você terá um conhecimento sólido para criar seus próprios scripts de monitoramento profissionais.

Verificando serviços e recursos

O primeiro passo em qualquer script de monitoramento é coletar informações sobre o estado atual do sistema. O PowerShell oferece cmdlets nativos para consultar serviços, processos, uso de CPU, memória, disco e muito mais. Vamos examinar os principais.

Para verificar serviços, usamos o cmdlet Get-Service. Ele retorna objetos que representam cada serviço, com propriedades como Status, Name e DisplayName. Podemos filtrar por status ou nome, e também verificar se um serviço específico está em execução. Por exemplo, para listar todos os serviços em execução:

Get-Service | Where-Object { $_.Status -eq 'Running' }

Para recursos do sistema, temos Get-Process para processos, Get-Counter para contadores de desempenho (como CPU e memória), e Get-PSDrive ou Get-Volume para discos. Um exemplo de verificação de uso de disco:

Get-Volume | Select-Object DriveLetter, FileSystemLabel, @{Name='Size(GB)';Expression={[math]::Round($_.Size/1GB,2)}}, @{Name='Free(GB)';Expression={[math]::Round($_.SizeRemaining/1GB,2)}}

Para monitorar CPU e memória, podemos usar Get-Counter:

$cpu = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
$mem = (Get-Counter '\Memory\Available MBytes').CounterSamples.CookedValue
Write-Host "CPU: $cpu% - Memória Livre: $mem MB"

Em scripts de monitoramento, é comum definir limites e verificar se os valores estão dentro do esperado. Por exemplo, se a CPU estiver acima de 90% por um período, pode ser um sinal de alerta. Vamos combinar essas verificações em um script simples que verifica serviços críticos e recursos:

$servicos = @('Spooler', 'W3SVC', 'MSSQLSERVER')
foreach ($svc in $servicos) {
    $status = (Get-Service -Name $svc -ErrorAction SilentlyContinue).Status
    if ($status -eq 'Running') {
        Write-Host "$svc está em execução" -ForegroundColor Green
    } else {
        Write-Host "$svc NÃO está em execução!" -ForegroundColor Red
    }
}

$cpuThreshold = 90
$cpu = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
if ($cpu -gt $cpuThreshold) {
    Write-Host "ALERTA: CPU acima de $cpuThreshold% ($cpu%)" -ForegroundColor Yellow
} else {
    Write-Host "CPU ok: $cpu%" -ForegroundColor Green
}

Alertas

De nada adianta monitorar se não formos notificados quando algo der errado. Alertas são essenciais para que possamos agir rapidamente. O PowerShell permite enviar alertas por e-mail, gravar em log, exibir pop-ups ou até mesmo enviar mensagens para serviços externos como Slack ou Teams (via webhooks).

O método mais comum é o envio de e-mail usando o cmdlet Send-MailMessage (embora em versões mais recentes seja recomendado usar Send-MailKitMessage ou a classe System.Net.Mail.SmtpClient). Um exemplo simples:

$parametrosEmail = @{
    From = 'monitor@empresa.com'
    To = 'admin@empresa.com'
    Subject = 'Alerta: Serviço parado'
    Body = 'O serviço Spooler está parado.'
    SmtpServer = 'smtp.empresa.com'
}
Send-MailMessage @parametrosEmail

Para alertas visuais, podemos usar o .NET Framework para exibir um balão de notificação ou um pop-up. Exemplo de pop-up com MsgBox:

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.MessageBox]::Show('Alerta: CPU alta!', 'Monitoramento')

Outra abordagem moderna é enviar um webhook para o Slack ou Teams. Aqui está um exemplo para Slack (usando um webhook URL):

$webhookUrl = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
$mensagem = @{ text = '🚨 Alerta: Serviço Spooler parado!' } | ConvertTo-Json
Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $mensagem -ContentType 'application/json'

Em nossos scripts, devemos integrar os alertas às verificações. Por exemplo, se um serviço crítico estiver parado, envie um e-mail e registre no log. Vamos criar uma função de alerta reutilizável:

function Send-Alerta {
    param(
        [string]$Mensagem,
        [string]$Severidade = 'Info'
    )
    # Enviar e-mail
    $parametrosEmail = @{
        From = 'monitor@empresa.com'
        To = 'admin@empresa.com'
        Subject = "[$Severidade] Alerta de Monitoramento"
        Body = $Mensagem
        SmtpServer = 'smtp.empresa.com'
    }
    Send-MailMessage @parametrosEmail
    # Registrar no log (será abordado na próxima seção)
    Write-Log -Mensagem $Mensagem -Severidade $Severidade
}

Logging

Manter um registro (log) das atividades e alertas é fundamental para auditoria e diagnóstico. O PowerShell oferece várias formas de criar logs: podemos gravar em arquivos de texto, usar o Event Viewer do Windows, ou até mesmo em bancos de dados.

Uma abordagem simples é criar um arquivo de log com data/hora e mensagens. Podemos definir uma função Write-Log que adiciona linhas a um arquivo:

function Write-Log {
    param(
        [string]$Mensagem,
        [string]$CaminhoLog = 'C:\Logs\monitoramento.log',
        [string]$Severidade = 'Info'
    )
    $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
    $linha = "[$timestamp] [$Severidade] $Mensagem"
    Add-Content -Path $CaminhoLog -Value $linha
}

Para usar o Event Viewer, podemos usar o cmdlet Write-EventLog (ou New-EventLog se precisar criar uma fonte). Exemplo:

if (-not [System.Diagnostics.EventLog]::SourceExists('MeuScriptMonitoramento')) {
    New-EventLog -LogName Application -Source 'MeuScriptMonitoramento'
}
Write-EventLog -LogName Application -Source 'MeuScriptMonitoramento' -EventId 1001 -EntryType Warning -Message 'Serviço Spooler parado.'

É importante incluir detalhes como horário, hostname, e o que estava sendo verificado. Um log bem estruturado facilita a correção de problemas. Vamos melhorar nossa função para incluir o nome do computador e o script:

function Write-Log {
    param(
        [string]$Mensagem,
        [string]$CaminhoLog = 'C:\Logs\monitoramento.log',
        [string]$Severidade = 'Info'
    )
    $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
    $hostname = $env:COMPUTERNAME
    $linha = "[$timestamp] [$hostname] [$Severidade] $Mensagem"
    Add-Content -Path $CaminhoLog -Value $linha
}

Podemos também configurar a rotação de logs para evitar que os arquivos cresçam indefinidamente, por exemplo, criando um novo arquivo por dia ou por tamanho máximo.

Execução periódica

Para que o monitoramento seja contínuo, precisamos executar nossos scripts em intervalos regulares. Existem duas abordagens principais: usar o Agendador de Tarefas do Windows ou criar um loop dentro do próprio script.

O Agendador de Tarefas é a forma mais profissional e confiável. Podemos criar uma tarefa que executa o script a cada X minutos, no logon ou em horários específicos. Para criar via PowerShell, usamos o módulo ScheduledTasks. Exemplo de criação de uma tarefa que executa o script a cada 5 minutos:

$acao = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-File "C:\Scripts\monitoramento.ps1"'
$gatilho = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Days 3650)
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable
Register-ScheduledTask -TaskName 'Monitoramento' -Action $acao -Trigger $gatilho -Settings $settings -Description 'Script de monitoramento periódico'

Outra opção é usar o Register-ScheduledTask com um gatilho de logon ou em um horário específico. Para mais controle, podemos usar o utilitário schtasks.exe.

Se preferir que o script fique em execução contínua, podemos usar um loop com Start-Sleep. Por exemplo, para verificar a cada 5 minutos:

while ($true) {
    # Verificações aqui
    Write-Log 'Verificação executada'
    Start-Sleep -Seconds 300
}

No entanto, essa abordagem não é recomendada para scripts longos, pois consome memória e pode ser interrompida se o PowerShell fechar. O Agendador de Tarefas é mais robusto e permite reiniciar após falhas.

Boas práticas e observações finais

Ao criar scripts de monitoramento, siga estas boas práticas para garantir robustez e manutenibilidade:

  • Use funções para encapsular lógica repetitiva, como verificação de serviços e envio de alertas.
  • Parametrize caminhos, e-mails e limites em variáveis ou arquivos de configuração.
  • Trate erros com try/catch para evitar que o script pare inesperadamente.
  • Inclua informações contextuais nos logs (hostname, timestamp, nome do script).
  • Teste os scripts manualmente antes de agendar.
  • Considere usar módulos como PSFramework para logging avançado, ou ferramentas como Posh-Sysmon.

Lembre-se de que monitorar é um processo contínuo; revise e ajuste seus scripts conforme a infraestrutura evolui.

Exercícios

  1. Crie um script que verifique se o serviço 'Spooler' está em execução. Se não estiver, exiba um alerta no console e envie um e-mail fictício (use Send-MailMessage com parâmetros fictícios).
  2. Escreva uma função Get-DiskHealth que retorne o espaço livre em disco de todas as unidades em GB, e alerte se alguma tiver menos de 10% de espaço livre.
  3. Implemente um sistema de logging que registre cada execução do script em um arquivo monitoramento.log, incluindo data/hora e status das verificações.
  4. Crie um script que monitore a CPU e a memória a cada 30 segundos, registrando um alerta se a CPU estiver acima de 80% ou a memória livre abaixo de 500 MB.
  5. Agende o script de monitoramento para rodar a cada 10 minutos usando o Agendador de Tarefas, e mostre o comando usado.

✓ Resposta:
$servico = Get-Service -Name 'Spooler' -ErrorAction SilentlyContinue
if ($servico -and $servico.Status -eq 'Running') {
    Write-Host 'Serviço Spooler em execução' -ForegroundColor Green
} else {
    Write-Host 'ALERTA: Serviço Spooler parado!' -ForegroundColor Red
    $parametrosEmail = @{
        From = 'monitor@empresa.com'
        To = 'admin@empresa.com'
        Subject = 'Alerta: Serviço Spooler parado'
        Body = 'O serviço Spooler está parado. Verifique imediatamente.'
        SmtpServer = 'smtp.empresa.com'
    }
    Send-MailMessage @parametrosEmail
}

✓ Resposta:
function Get-DiskHealth {
    $volumes = Get-Volume
    foreach ($vol in $volumes) {
        if ($vol.Size -gt 0) {
            $percentFree = ($vol.SizeRemaining / $vol.Size) * 100
            if ($percentFree -lt 10) {
                Write-Host "ALERTA: Unidade $($vol.DriveLetter) com $([math]::Round($percentFree,2))% livre." -ForegroundColor Red
            } else {
                Write-Host "Unidade $($vol.DriveLetter): $([math]::Round($percentFree,2))% livre." -ForegroundColor Green
            }
        }
    }
}
Get-DiskHealth

✓ Resposta:
function Write-Log {
    param(
        [string]$Mensagem,
        [string]$CaminhoLog = 'C:\Logs\monitoramento.log',
        [string]$Severidade = 'Info'
    )
    $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
    $hostname = $env:COMPUTERNAME
    $linha = "[$timestamp] [$hostname] [$Severidade] $Mensagem"
    Add-Content -Path $CaminhoLog -Value $linha
}

# Exemplo de uso
Write-Log 'Script iniciado'
# ... verificações ...
Write-Log 'Script finalizado'

✓ Resposta:
while ($true) {
    $cpu = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
    $mem = (Get-Counter '\Memory\Available MBytes').CounterSamples.CookedValue
    if ($cpu -gt 80 -or $mem -lt 500) {
        Write-Host "ALERTA: CPU $cpu% - Memória $mem MB" -ForegroundColor Red
        Write-Log "ALERTA: CPU $cpu% - Memória $mem MB" -Severidade 'Warning'
    } else {
        Write-Host "OK: CPU $cpu% - Memória $mem MB" -ForegroundColor Green
        Write-Log "OK: CPU $cpu% - Memória $mem MB"
    }
    Start-Sleep -Seconds 30
}

✓ Resposta:
$acao = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-File "C:\Scripts\monitoramento.ps1"'
$gatilho = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 10) -RepetitionDuration (New-TimeSpan -Days 3650)
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable
Register-ScheduledTask -TaskName 'Monitoramento' -Action $acao -Trigger $gatilho -Settings $settings -Description 'Script de monitoramento periódico'

Referências