Como criar dashboards simples com PowerShell e HTML
1. Introdução ao conceito de dashboards com PowerShell e HTML
Dashboards são ferramentas essenciais para visualização de dados em tempo real ou quase real. Quando combinamos PowerShell com HTML, criamos uma solução leve, portátil e altamente personalizável para gerar relatórios visuais sem depender de ferramentas pesadas como Power BI ou Tableau.
A principal vantagem dessa abordagem é a portabilidade: um arquivo HTML pode ser aberto em qualquer navegador, compartilhado por e-mail, hospedado em servidores web ou acessado em redes locais. PowerShell, por sua vez, oferece acesso nativo a dados do sistema Windows, logs de eventos, serviços, processos e muito mais.
Cenários práticos incluem relatórios de saúde do servidor, monitoramento de serviços críticos, auditoria de eventos de segurança e dashboards de desempenho para equipes de infraestrutura.
2. Preparação do ambiente e fontes de dados
Antes de gerar o dashboard, precisamos coletar dados confiáveis. PowerShell oferece cmdlets poderosos para essa finalidade:
# Coleta de dados do sistema
$processos = Get-Process | Select-Object -First 10 Name, CPU, WorkingSet
$servicos = Get-Service | Where-Object { $_.Status -eq 'Running' }
$eventos = Get-EventLog -LogName System -Newest 20
# Estruturando dados em hashtable para facilitar o acesso
$dadosServidor = @{
Nome = $env:COMPUTERNAME
CPU = (Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average
MemoriaTotal = (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB
MemoriaLivre = (Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB
DiscoLivre = (Get-PSDrive C | Select-Object -ExpandProperty Free) / 1GB
}
Tratamento de erros é crucial. Use try/catch para garantir que falhas na coleta não quebrem a geração do dashboard:
try {
$cpu = (Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average
} catch {
$cpu = 0
Write-Warning "Não foi possível obter dados de CPU"
}
3. Construção da estrutura HTML base via PowerShell
A estrutura HTML pode ser montada usando here-strings, que permitem criar blocos de texto multilinha com variáveis interpoladas:
$htmlTemplate = @"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Dashboard - $($dadosServidor.Nome)</title>
<style>
body { font-family: 'Segoe UI', sans-serif; margin: 20px; background: #f5f5f5; }
.container { max-width: 1200px; margin: auto; }
.card { background: white; border-radius: 8px; padding: 20px; margin: 10px 0; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
h1 { color: #333; border-bottom: 3px solid #0078d4; padding-bottom: 10px; }
table { width: 100%; border-collapse: collapse; }
th { background: #0078d4; color: white; padding: 10px; text-align: left; }
td { padding: 8px; border-bottom: 1px solid #ddd; }
tr:nth-child(even) { background: #f9f9f9; }
.metric { display: inline-block; margin: 10px; padding: 15px; min-width: 200px; }
.metric-value { font-size: 2em; font-weight: bold; color: #0078d4; }
.progress-bar { height: 20px; background: #e0e0e0; border-radius: 10px; overflow: hidden; }
.progress-fill { height: 100%; background: #0078d4; border-radius: 10px; transition: width 0.3s; }
.critical { color: #d32f2f; }
.warning { color: #f57c00; }
.ok { color: #388e3c; }
</style>
</head>
<body>
<div class='container'>
<h1>📊 Dashboard - $($dadosServidor.Nome)</h1>
"@
4. Geração de tabelas e gráficos simples
O cmdlet ConvertTo-Html é a maneira mais rápida de converter objetos em tabelas HTML, mas podemos personalizá-lo:
# Tabela personalizada de processos
$tabelaProcessos = $processos | ConvertTo-Html -Fragment -PreContent "<h2>Processos em Execução</h2>" | Out-String
# Para mais controle, montamos manualmente
$tabelaServicos = "<h2>Serviços Ativos</h2><table><tr><th>Nome</th><th>Status</th><th>Tipo</th></tr>"
foreach ($svc in $servicos) {
$statusClass = "ok"
if ($svc.Status -eq 'Stopped') { $statusClass = "critical" }
$tabelaServicos += "<tr><td>$($svc.Name)</td><td class='$statusClass'>$($svc.Status)</td><td>$($svc.ServiceType)</td></tr>"
}
$tabelaServicos += "</table>"
Gráficos de barras simples podem ser criados com divs estilizadas:
# Gráfico de barras para uso de CPU por processo
$graficoCPU = "<h2>Uso de CPU por Processo (Top 5)</h2>"
$topCPU = $processos | Sort-Object CPU -Descending | Select-Object -First 5
$maxCPU = ($topCPU | Measure-Object CPU -Maximum).Maximum
foreach ($proc in $topCPU) {
$percent = [math]::Round(($proc.CPU / $maxCPU) * 100, 0)
$graficoCPU += @"
<div style='margin: 5px 0;'>
<span>$($proc.Name)</span>
<div class='progress-bar'>
<div class='progress-fill' style='width: $percent%'></div>
</div>
<span>$([math]::Round($proc.CPU, 2))%</span>
</div>
"@
}
5. Adição de indicadores visuais e métricas
Cards de resumo com indicadores visuais tornam o dashboard mais informativo:
function New-MetricCard {
param($Titulo, $Valor, $Unidade, $LimiteCritico, $LimiteAlerta)
$classe = "ok"
if ($Valor -gt $LimiteCritico) { $classe = "critical" }
elseif ($Valor -gt $LimiteAlerta) { $classe = "warning" }
return @"
<div class='card metric'>
<h3>$Titulo</h3>
<div class='metric-value $classe'>$([math]::Round($Valor, 1)) $Unidade</div>
<div class='progress-bar'>
<div class='progress-fill' style='width: $([math]::Min($Valor, 100))%; background: $(if($classe -eq 'critical'){'#d32f2f'}elseif($classe -eq 'warning'){'#f57c00'}else{'#0078d4'})'></div>
</div>
</div>
"@
}
$cardsMetricas = @"
<div style='display: flex; flex-wrap: wrap;'>
$(New-MetricCard -Titulo "CPU" -Valor $dadosServidor.CPU -Unidade "%" -LimiteCritico 90 -LimiteAlerta 70)
$(New-MetricCard -Titulo "Memória Usada" -Valor (100 - ($dadosServidor.MemoriaLivre / ($dadosServidor.MemoriaTotal * 1024)) * 100) -Unidade "%" -LimiteCritico 95 -LimiteAlerta 85)
$(New-MetricCard -Titulo "Disco C:" -Valor (100 - ($dadosServidor.DiscoLivre / 100) * 100) -Unidade "%" -LimiteCritico 95 -LimiteAlerta 85)
</div>
"@
6. Automação e atualização do dashboard
Crie uma função reutilizável para gerar o dashboard:
function New-ServerDashboard {
param(
[string]$OutputPath = "C:\Dashboards\dashboard.html",
[switch]$OpenBrowser
)
# Coleta de dados (código das seções anteriores)
# Montagem do HTML (código das seções anteriores)
$htmlCompleto = $htmlTemplate + $cardsMetricas + $tabelaProcessos + $tabelaServicos + $graficoCPU + "</div></body></html>"
$htmlCompleto | Out-File -FilePath $OutputPath -Encoding UTF8
if ($OpenBrowser) {
Start-Process $OutputPath
}
Write-Host "Dashboard gerado em: $OutputPath"
}
# Exemplo de uso
New-ServerDashboard -OpenBrowser
Para agendamento automático, use o Task Scheduler do Windows:
# Comando para criar tarefa agendada (executar como Administrador)
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-File C:\Scripts\GerarDashboard.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "08:00"
Register-ScheduledTask -TaskName "DashboardServidor" -Action $action -Trigger $trigger -User "SYSTEM"
7. Exemplo prático completo: Dashboard de monitoramento de servidor
Abaixo, um exemplo funcional completo que integra todos os conceitos:
# dashboard_completo.ps1
$dataGeracao = Get-Date -Format "dd/MM/yyyy HH:mm"
# Coleta
$cpu = [math]::Round((Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average, 1)
$memTotal = (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB
$memLivre = (Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB
$memUsada = [math]::Round((1 - ($memLivre / ($memTotal * 1024))) * 100, 1)
$discoLivre = (Get-PSDrive C).Free / 1GB
$discoTotal = (Get-PSDrive C).Used / 1GB + $discoLivre
$discoUsado = [math]::Round(($discoTotal - $discoLivre) / $discoTotal * 100, 1)
$servicosCriticos = @("Spooler", "W3SVC", "MSSQLSERVER")
$statusServicos = foreach ($s in $servicosCriticos) {
$svc = Get-Service -Name $s -ErrorAction SilentlyContinue
[PSCustomObject]@{
Nome = $s
Status = if ($svc) { $svc.Status } else { "Inexistente" }
}
}
# Montagem HTML (simplificada)
$html = @"
<!DOCTYPE html>
<html>
<head><title>Dashboard - $env:COMPUTERNAME</title>
<style>
body { font-family: Arial; background: #f0f0f0; padding: 20px; }
.card { background: white; border-radius: 10px; padding: 20px; margin: 15px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; }
.valor { font-size: 2.5em; font-weight: bold; }
.critico { color: red; }
.barrinha { height: 25px; background: #e0e0e0; border-radius: 12px; margin: 10px 0; }
.barrinha div { height: 100%; border-radius: 12px; }
</style></head>
<body>
<h1>📊 Dashboard - $env:COMPUTERNAME</h1>
<p>Gerado em: $dataGeracao</p>
<div class='grid'>
<div class='card'><h3>CPU</h3><div class='valor $(if($cpu -gt 90){'critico'})'>$cpu%</div><div class='barrinha'><div style='width:$cpu%;background:$(if($cpu -gt 90){'red'}else{'#0078d4'})'></div></div></div>
<div class='card'><h3>Memória</h3><div class='valor $(if($memUsada -gt 95){'critico'})'>$memUsada%</div><div class='barrinha'><div style='width:$memUsada%;background:$(if($memUsada -gt 95){'red'}else{'#0078d4'})'></div></div></div>
<div class='card'><h3>Disco C:</h3><div class='valor $(if($discoUsado -gt 95){'critico'})'>$discoUsado%</div><div class='barrinha'><div style='width:$discoUsado%;background:$(if($discoUsado -gt 95){'red'}else{'#0078d4'})'></div></div></div>
</div>
<div class='card'>
<h3>Serviços Críticos</h3>
<table><tr><th>Serviço</th><th>Status</th></tr>
$($statusServicos | ForEach-Object { "<tr><td>$($_.Nome)</td><td style='color:$(if($_.Status -eq 'Running'){'green'}else{'red'})'>$($_.Status)</td></tr>" })
</table>
</div>
</body></html>
"@
$html | Out-File "C:\Dashboard\servidor.html" -Encoding UTF8
Start-Process "C:\Dashboard\servidor.html"
8. Boas práticas e extensões possíveis
Para manter o código sustentável, separe a lógica em módulos:
# Estrutura de pastas recomendada
# C:\Scripts\Dashboard\
# ├── ColetaDados.ps1
# ├── TemplateHTML.ps1
# ├── GerarDashboard.ps1
# └── Agendamento.ps1
Para dashboards mais profissionais, integre frameworks CSS como Bootstrap:
# Adicione no <head> do HTML
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
Extensões possíveis incluem integração com bancos de dados SQL via Invoke-SqlCmd, consumo de APIs REST com Invoke-RestMethod, geração de gráficos com Chart.js (adicionando JavaScript ao HTML) e envio por e-mail com Send-MailMessage.
Referências
- Documentação oficial do PowerShell - ConvertTo-Html — Referência completa do cmdlet para converter objetos em fragmentos HTML.
- PowerShell HTML Dashboard Tutorial - Adam the Automator — Guia prático com exemplos de dashboards de monitoramento usando PowerShell e HTML.
- Using PowerShell to Create HTML Reports - Scripting Blog — Artigo técnico da Microsoft sobre geração de relatórios HTML com PowerShell.
- PowerShell Gallery - PSWriteHTML Module — Módulo da comunidade que facilita a criação de dashboards HTML avançados com PowerShell.
- Task Scheduler with PowerShell Scripts - 4sysops — Tutorial sobre agendamento de scripts PowerShell usando o Agendador de Tarefas do Windows.
- Bootstrap 5 Documentation — Documentação oficial do framework CSS Bootstrap para estilização profissional de dashboards.
- PowerShell and HTML: Creating Dynamic Reports - Redmond Mag — Artigo aprofundado sobre técnicas de geração dinâmica de relatórios HTML com PowerShell.