Se você está escrevendo scripts do PowerShell que fazem algo significativo, você precisa de registro. Seja para implantar software, gerenciar serviços ou automatizar 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 do PowerShell simples, mas eficaz.
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 (recomendado o VSCode)
- Conhecimento básico de funções do PowerShell
O Problema com o 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 tem alguns problemas:
- Sem carimbos de hora
- Código repetitivo
- Formato de registro inconsistente
- Caminho de log codificado
Vamos corrigir esses problemas construindo uma função de registro apropriada.
Construindo uma Função Básica de Write-Log
Primeiro, vamos criar uma função simples que adiciona carimbos de 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á-lo 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 melhorar.
Adicionando Mais Funcionalidades
Vamos aprimorar nossa função de registro com algumas funcionalidades úteis:
- Caminhos de log personalizados
- Diferentes níveis de log (Informação, Aviso, Erro)
- Data no nome do arquivo
- Tratamento de erros
Aqui está a versão aprimorada:
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) terá esta aparência:
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
Note como cada entrada inclui a marcação de tempo, o 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 em prática em um script real que instala software em silêncio:
# 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 terá uma aparência semelhante a esta:
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 melhores 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 níveis de log apropriados – Não marque tudo como um erro; use o nível certo 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 – Registrar informações suficientes para entender o que aconteceu:
# Ruim Write-Log "Falha ao se conectar" # Bom Write-Log "Falha ao se conectar ao servidor 'SQL01' - tempo esgotado após 30 segundos" -Nível Erro
-
Limpar logs antigos – Considere adicionar rotação de logs para evitar o preenchimento do espaço em disco:
# Excluir logs mais antigos que 30 dias Get-ChildItem -Caminho $CaminhoLog -Filtro "*.txt" | Onde-Objeto { $_.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, você agora 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 evoluir a partir daí com base em suas necessidades específicas. Esses exemplos devem lhe dar 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 abrangente de registro:
Write-Log -Message "Critical error in payment processing" ` -Level Error ` -Format CSV ` -NetworkPath "\\\\server\\logs" ` -NotifyOnError "[email protected]","[email protected]" ` -MaxLogFiles 90
Isso iria:
- Registrar o erro em formato CSV
- Armazená-lo em um compartilhamento de rede
- Enviar por e-mail para vários destinatários
- Manter um histórico de log de 90 dias
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. Feliz script!
Source:
https://adamtheautomator.com/powershell-write-log-tutorial/