Logging em scripts PowerShell
LidoEsta aula ensina como implementar logging eficaz em scripts PowerShell, cobrindo desde o uso de Start-Transcript até a criação de funções de log personalizadas, a compreensão dos diferentes streams e boas práticas para produção. Ao final, você será capaz de adicionar rastreabilidade e facilitar a depuração dos seus scripts.
Logging é o processo de registrar informações sobre a execução de um script, como erros, avisos e etapas concluídas. Em scripts PowerShell, especialmente aqueles que automatizam tarefas críticas ou rodam de forma agendada, um bom sistema de log é essencial para auditar, depurar e monitorar o comportamento do script. Nesta aula, vamos explorar as ferramentas nativas do PowerShell e técnicas para criar logs robustos e informativos.
Dominar o logging não só ajuda a identificar problemas rapidamente, mas também fornece um histórico valioso para otimizar scripts e garantir conformidade com políticas de TI. Vamos começar com o cmdlet Start-Transcript, depois evoluiremos para funções personalizadas que oferecem controle total sobre o formato e o destino dos logs.
Start-Transcript
O cmdlet Start-Transcript é a maneira mais simples de registrar toda a saída de uma sessão do PowerShell em um arquivo de texto. Ele captura tudo o que aparece no console, incluindo comandos executados e suas saídas, como se fosse uma gravação de tela. Isso é particularmente útil para scripts que precisam de um registro completo de sua execução, sem exigir nenhuma modificação no código além de iniciar e parar a transcrição.
Para usar, basta chamar Start-Transcript -Path "C:\Logs\meuscript.log" no início do script e Stop-Transcript no final. O arquivo será criado (ou sobrescrito, por padrão) e conterá todo o texto exibido. Porém, é importante notar que ele não captura saídas de streams separados (como erros) de forma estruturada; tudo é misturado em texto plano. Além disso, o arquivo pode crescer rapidamente em scripts longos. Ainda assim, é uma ferramenta valiosa para depuração rápida e para ambientes onde não se deseja criar uma infraestrutura de logging mais complexa.
# Iniciar a transcrição
Start-Transcript -Path "C:\Logs\meuscript.log" -Force
# Seu código aqui
Write-Host "Executando tarefa..."
Get-Process | Select-Object -First 3
# Parar a transcrição
Stop-TranscriptO parâmetro -Force sobrescreve o arquivo existente; sem ele, o cmdlet perguntaria se deseja sobrescrever. Em scripts não interativos, é recomendável usar -Force ou gerar nomes de arquivo únicos (ex.: com timestamp).
Funções de log
Embora o Start-Transcript seja útil, muitas vezes precisamos de logs mais estruturados, com níveis de severidade (INFO, WARN, ERROR) e controle sobre o que é registrado. Criar funções de log personalizadas é a abordagem profissional. Você pode definir uma função que aceita uma mensagem e um nível, e que grava em um arquivo com formato consistente, por exemplo, CSV ou JSON, além de permitir exibir no console quando desejado.
Uma função de log típica pode incluir timestamp, nível e mensagem. Você pode usar o cmdlet Add-Content para anexar linhas a um arquivo de texto. Para logs mais avançados, considere usar o módulo PSFramework (da comunidade) ou o Microsoft.PowerShell.Utility com Write-Log (se disponível). Vamos criar uma função simples e reutilizável.
function Write-Log {
param(
[Parameter(Mandatory)]
[string]$Message,
[ValidateSet('INFO','WARN','ERROR')]
[string]$Level = 'INFO',
[string]$LogFile = "C:\Logs\script.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logLine = "$timestamp [$Level] $Message"
# Exibir no console se verboso ou se for erro
if ($Level -eq 'ERROR' -or $VerbosePreference -eq 'Continue') {
Write-Host $logLine
}
# Gravar no arquivo
Add-Content -Path $LogFile -Value $logLine
}Com essa função, você pode chamar Write-Log -Message "Iniciando processo" -Level INFO e Write-Log -Message "Falha ao conectar" -Level ERROR. Essa abordagem permite que você controle o nível de detalhe, filtre por severidade e integre-se a sistemas de monitoramento. Em produção, você pode querer usar um formato estruturado como JSON para facilitar o parsing por ferramentas como o Elastic Stack.
Streams
O PowerShell possui vários streams de saída, cada um com um propósito específico: Success (saída normal), Error, Warning, Verbose, Debug e Information. Entender esses streams é crucial para logging, pois você pode redirecioná-los e capturá-los seletivamente.
Por exemplo, o stream de erro é onde os erros não-terminantes são enviados. Você pode redirecionar todos os streams para um arquivo usando *> arquivo.log, mas isso mistura tudo. Para capturar streams específicos, você pode usar 2>&1 para redirecionar erros para a saída padrão, ou usar os cmdlets Write-Error, Write-Warning, Write-Verbose, etc., que enviam mensagens para os respectivos streams. No logging, é comum registrar erros e avisos separadamente, ou usar os streams para controlar a verbosidade do script.
# Exemplo de uso de streams
Write-Output "Mensagem normal"
Write-Warning "Este é um aviso"
Write-Error "Este é um erro não-terminante"
Write-Verbose "Mensagem detalhada" -Verbose
# Redirecionar todos os streams para um arquivo
Start-Transcript -Path "C:\Logs\transcript.log" -Force
Write-Output "Executando..."
Write-Warning "Cuidado"
Stop-Transcript
# Capturar erros em variável
$erros = 2>&1 # não é assim; melhor usar try/catchNa prática, você pode definir a preferência de verbosidade com $VerbosePreference = 'Continue' para que mensagens verbose apareçam no console e, se estiver usando transcrição, sejam capturadas. Para logs estruturados, você pode usar Write-Information com o parâmetro -InformationAction para controlar a exibição.
Boas práticas
Ao implementar logging, siga estas recomendações para garantir que seus logs sejam úteis e confiáveis:
- Inclua timestamps e nível de severidade em cada entrada para facilitar a análise.
- Use nomes de arquivo com data/hora para evitar sobrescritas e permitir histórico (ex.:
script-20250301.log). - Capture o contexto: além da mensagem, registre o nome do script, função, linha (se possível) e o usuário que executou.
- Não misture streams sem necessidade; use um formato estruturado (CSV, JSON) se for processar logs automaticamente.
- Lide com erros de forma consistente: use
try/catche registre o erro com detalhes (ex.:$_.Exception.Message). - Evite logs excessivos em produção; use níveis (INFO, DEBUG) e ajuste conforme o ambiente.
- Teste o logging em cenários de falha para garantir que os erros são capturados.
- Considere a rotação de logs para arquivos muito grandes.
# Exemplo de bloco try/catch com log
function Invoke-Tarefa {
param([string]$Caminho)
try {
if (-not (Test-Path $Caminho)) {
throw "Arquivo não encontrado: $Caminho"
}
Write-Log -Message "Processando $Caminho" -Level INFO
# ... processamento ...
}
catch {
Write-Log -Message "Erro: $($_.Exception.Message)" -Level ERROR
throw # relança o erro para o chamador
}
}Além disso, ao usar funções de log, defina um parâmetro comum para o caminho do arquivo de log, permitindo que o usuário do script configure o destino sem alterar o código. Em scripts maiores, você pode criar um módulo de logging reutilizável.
Referências
- Documentação oficial do Start-Transcript
- Documentação do Stop-Transcript
- Sobre redirecionamento de streams
- Tratamento de erros no PowerShell
- Variáveis de preferência do PowerShell
- Criando funções personalizadas
- Add-Content para escrever em arquivos
Exercícios
- Exercício 1: Escreva um script que use Start-Transcript para registrar a saída de um comando simples (ex.: Get-Process) e salve o log em um arquivo chamado "processos.log".
- Exercício 2: Crie uma função chamada Write-Log que aceite mensagem, nível (INFO, WARN, ERROR) e arquivo de log, e escreva uma linha formatada com timestamp. Teste a função com uma chamada de exemplo.
- Exercício 3: Explique a diferença entre os streams de saída e como você pode redirecionar apenas erros para um arquivo separado. Dê um exemplo de código.
- Exercício 4: Reescreva o script abaixo para incluir tratamento de erros com try/catch e registre os erros em um log usando uma função Write-Log. O script tenta ler um arquivo que pode não existir.
- Exercício 5: Liste três boas práticas de logging que você aplicaria em um script de produção e explique por que cada uma é importante.
Start-Transcript -Path "C:\Logs\processos.log" -Force
Get-Process
Stop-Transcriptfunction Write-Log {
param(
[Parameter(Mandatory)]
[string]$Message,
[ValidateSet('INFO','WARN','ERROR')]
[string]$Level = 'INFO',
[string]$LogFile = "C:\Logs\script.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logLine = "$timestamp [$Level] $Message"
Add-Content -Path $LogFile -Value $logLine
}
# Exemplo de uso
Write-Log -Message "Script iniciado" -Level INFO2> erro.log. Exemplo:Write-Error "Este é um erro" 2> "C:\Logs\erros.log"function Write-Log {
param($Message, $Level = 'INFO', $LogFile = "C:\Logs\script.log")
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$line = "$ts [$Level] $Message"
Add-Content -Path $LogFile -Value $line
}
try {
Get-Content "C:\arquivo_inexistente.txt" -ErrorAction Stop
}
catch {
Write-Log -Message "Erro ao ler arquivo: $($_.Exception.Message)" -Level ERROR
}Observações finais
O logging é uma habilidade essencial para qualquer profissional que trabalha com PowerShell em automação. Comece com Start-Transcript para depuração rápida, mas evolua para funções personalizadas que oferecem controle e estrutura. Lembre-se de considerar os streams e as boas práticas apresentadas para criar logs que realmente ajudem no monitoramento e na resolução de problemas. À medida que você ganha experiência, explore ferramentas avançadas como o módulo PSFramework ou integração com sistemas de log centralizados (ELK, Splunk).