Se você está escrevendo scripts PowerShell que fazem algo significativo, você precisa de registro. Seja implementando software, gerenciando serviços ou automatizando tarefas, ter um registro do que seu script fez (ou não fez) é crucial. Neste tutorial, você aprenderá como criar uma função de registro simples, mas eficaz, no PowerShell.
Pré-requisitos
Se você deseja acompanhar este tutorial, certifique-se de ter:
- Windows 10 ou Windows Server com PowerShell 5.1 ou PowerShell 7+
- Um editor de texto (VSCode recomendado)
- Compreensão básica das funções do PowerShell
O Problema com Registro Básico
Vamos dizer que você está escrevendo um script para instalar silenciosamente algum software. A abordagem básica pode ser algo assim:
Add-Content -Path "C:\\Scripts\\install.log" -Value "Starting install..." Start-Process -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow Add-Content -Path "C:\\Scripts\\install.log" -Value "Finished install."
Isso funciona, mas apresenta alguns problemas:
- Sem carimbos de data/hora
- Código repetitivo
- Formato de registro inconsistente
- Caminho de log codificado
Vamos corrigir esses problemas construindo uma função de registro adequada.
Construindo uma Função Write-Log Básica
Primeiro, vamos criar uma função simples que adiciona carimbos de data/hora às nossas entradas de log:
function Write-Log { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Message ) $timeGenerated = Get-Date -Format HH:mm:ss Add-Content -Path "C:\\Scripts\\script.log" -Value "$timeGenerated - $Message" }
Agora você pode usá-la assim:
Write-Log -Message "Starting install..." Start-Process -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow Write-Log -Message "Finished install."
O arquivo de log (C:\Scripts\script.log) conterá entradas que se parecem com:
09:42:15 - Starting install... 09:43:22 - Finished install.
Muito mais limpo! Mas podemos fazer melhor.
Adicionando Mais Funcionalidade
Vamos aprimorar nossa função de registro com alguns recursos úteis:
- Caminhos de log personalizados
- Diferentes níveis de log (Info, Aviso, Erro)
- Data no nome do arquivo
- Tratamento de erro
Aqui está a versão melhorada:
function Write-Log { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Message, [Parameter()] [ValidateNotNullOrEmpty()] [string]$LogFilePath = "C:\\Scripts\\Logs", [Parameter()] [ValidateSet('Information','Warning','Error')] [string]$Level = "Information" ) # Create the log directory if it doesn't exist if (!(Test-Path $LogFilePath)) { New-Item -Path $LogFilePath -ItemType Directory -Force | Out-Null } # Build the log file path with date $date = Get-Date -Format "MM-dd-yyyy" $logFile = Join-Path $LogFilePath "log-$date.txt" # Get the current timestamp $timeStamp = Get-Date -Format "HH:mm:ss" # Create the log entry $logEntry = "$timeStamp [$Level] - $Message" try { Add-Content -Path $logFile -Value $logEntry -ErrorAction Stop } catch { Write-Error "Failed to write to log file: $_" } }
Esta versão aprimorada oferece muito mais flexibilidade. Veja como usá-la:
# Basic information logging Write-Log -Message "Starting software installation" # Warning about a non-critical issue Write-Log -Message "Config file not found, using defaults" -Level Warning # Log an error Write-Log -Message "Installation failed!" -Level Error # Use a custom log path Write-Log -Message "Custom path log" -LogFilePath "D:\\CustomLogs"
O arquivo de log resultante (log-03-12-2024.txt) ficará assim:
10:15:22 [Information] - Starting software installation 10:15:23 [Warning] - Config file not found, using defaults 10:15:25 [Error] - Installation failed!
E em D:\CustomLogs\log-03-12-2024.txt:
10:15:26 [Information] - Custom path log
Observe como cada entrada inclui o carimbo de data/hora, nível de log entre colchetes e a mensagem. Este formato estruturado facilita a análise de logs e a identificação rápida de problemas.
Exemplo do mundo real: Script de Instalação de Software
Vamos colocar nossa função de log para trabalhar em um script real que instala software silenciosamente:
# First, dot-source the logging function . .\\Write-Log.ps1 # Script variables $installer = "C:\\Installers\\software.exe" $logPath = "C:\\Scripts\\InstallLogs" # Start logging Write-Log -Message "Beginning installation process" -LogFilePath $logPath # Check if installer exists if (Test-Path $installer) { Write-Log -Message "Found installer at: $installer" try { # Attempt installation Write-Log -Message "Starting installation..." $process = Start-Process -FilePath $installer -ArgumentList '/i /s' -Wait -NoNewWindow -PassThru # Check the exit code if ($process.ExitCode -eq 0) { Write-Log -Message "Installation completed successfully" } else { Write-Log -Message "Installation failed with exit code: $($process.ExitCode)" -Level Error } } catch { Write-Log -Message "Installation failed with error: $_" -Level Error } } else { Write-Log -Message "Installer not found at: $installer" -Level Error } Write-Log -Message "Installation script completed"
O arquivo de log resultante será algo assim:
09:15:22 [Information] - Beginning installation process 09:15:22 [Information] - Found installer at: C:\\Installers\\software.exe 09:15:22 [Information] - Starting installation... 09:16:45 [Information] - Installation completed successfully 09:16:45 [Information] - Installation script completed
Dicas úteis
Aqui estão algumas boas práticas ao usar esta função de log:
-
Sempre registre o início e o fim do seu script – Isso ajuda a rastrear o tempo de execução do script e o status de conclusão.
-
Use os níveis de log apropriados – Não marque tudo como erro; use o nível correto para a situação:
- Informação: Operações normais
- Aviso: Problemas não críticos
- Erro: Problemas críticos que precisam de atenção
-
Incluir detalhes relevantes – Registar informação suficiente para compreender o que aconteceu:
# Ruim Write-Log "Falha ao conectar" # Bom Write-Log "Falha ao conectar ao servidor 'SQL01' - tempo limite após 30 segundos" -Nível Erro
-
Limpar logs antigos – Considere adicionar rotação de logs para evitar ocupar espaço em disco:
# Excluir logs mais antigos que 30 dias Get-ChildItem -Path $CaminhoDoLog -Filter "*.txt" | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } | Remover-Item
Conclusão
Uma boa função de logging é essencial para qualquer script PowerShell sério. Com a função Write-Log
que construímos, agora você tem uma maneira flexível e reutilizável de adicionar logging adequado a todos os seus scripts. Lembre-se de adaptar a função às suas necessidades específicas – você pode querer adicionar recursos como:
Rotação de Logs
function Write-Log { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Message, [Parameter()] [int]$MaxLogFiles = 30 # Keep last 30 days of logs ) # Remove old log files Get-ChildItem -Path $LogFilePath -Filter "*.txt" | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$MaxLogFiles) } | Remove-Item -Force # Continue with normal logging... }
Diferentes Formatos de Saída (CSV, JSON)
function Write-Log { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Message, [Parameter()] [ValidateSet('TXT','CSV','JSON')] [string]$Format = 'TXT' ) $logEntry = [PSCustomObject]@{ Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" Level = $Level Message = $Message } switch ($Format) { 'CSV' { $logEntry | Export-Csv -Path "$LogFilePath\\log.csv" -Append -NoTypeInformation } 'JSON' { $logEntry | ConvertTo-Json | Add-Content -Path "$LogFilePath\\log.json" } 'TXT' { "$($logEntry.Timestamp) [$($logEntry.Level)] - $($logEntry.Message)" | Add-Content -Path "$LogFilePath\\log.txt" } } }
Suporte a Caminho de Rede
function Write-Log { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Message, [Parameter()] [string]$NetworkPath = "\\\\server\\logs" ) # Test network path connectivity if (!(Test-Path $NetworkPath)) { # Fallback to local logging if network is unavailable $NetworkPath = "C:\\Scripts\\Logs" Write-Warning "Network path unavailable. Using local path: $NetworkPath" } # Continue with normal logging... }
Notificações por Email para Erros
function Write-Log { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Message, [Parameter()] [string]$SmtpServer = "smtp.company.com", [Parameter()] [string[]]$NotifyOnError = "[email protected]" ) # Normal logging first... # Send email if this is an error if ($Level -eq 'Error' -and $NotifyOnError) { $emailParams = @{ From = "[email protected]" To = $NotifyOnError Subject = "PowerShell Script Error" Body = "Error occurred at $timeStamp`n`nMessage: $Message" SmtpServer = $SmtpServer } try { Send-MailMessage @emailParams } catch { Write-Warning "Failed to send error notification: $_" } } }
O segredo é começar com uma base sólida e construir a partir dela com base nas suas necessidades específicas. Estes exemplos devem dar-lhe um bom ponto de partida para estender a função básica de logging com recursos mais avançados.
Por exemplo, você pode combinar várias dessas funcionalidades em uma única solução de registro abrangente:
Write-Log -Message "Critical error in payment processing" ` -Level Error ` -Format CSV ` -NetworkPath "\\\\server\\logs" ` -NotifyOnError "[email protected]","[email protected]" ` -MaxLogFiles 90
Isso:
- Registra o erro em formato CSV
- Armazena em um compartilhamento de rede
- Envia e-mails para vários destinatários
- Mantém 90 dias de histórico de logs
Lembre-se de testar minuciosamente, especialmente ao implementar caminhos de rede ou notificações por e-mail, pois essas dependências externas podem afetar a confiabilidade do seu script. Boa programação!
Source:
https://adamtheautomator.com/powershell-write-log-tutorial/