Si vous écrivez des scripts PowerShell qui font quelque chose de significatif, vous avez besoin de logs. Que vous déployiez des logiciels, gériez des services ou automatisiez des tâches, avoir un enregistrement de ce que votre script a fait (ou n’a pas fait) est crucial. Dans ce tutoriel, vous apprendrez comment créer une fonction de journalisation PowerShell simple mais efficace.
Prérequis
Si vous souhaitez suivre ce tutoriel, assurez-vous d’avoir :
- Windows 10 ou Windows Server avec PowerShell 5.1 ou PowerShell 7+
- Un éditeur de texte (VSCode recommandé)
- Une compréhension de base des fonctions PowerShell
Le Problème avec la Journalisation Basique
Disons que vous écrivez un script pour installer silencieusement un logiciel. L’approche de base pourrait ressembler à ceci :
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."
Cela fonctionne, mais présente quelques problèmes :
- Pas de timestamp
- Code répétitif
- Format de journalisation incohérent
- Chemin de journalisation codé en dur
Corrigeons ces problèmes en construisant une fonction de journalisation adéquate.
Construction d’une Fonction Write-Log de Base
Tout d’abord, créons une fonction simple qui ajoute des timestamps à nos entrées de journal :
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" }
Maintenant, vous pouvez l’utiliser comme ceci :
Write-Log -Message "Starting install..." Start-Process -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow Write-Log -Message "Finished install."
Le fichier journal (C:\Scripts\script.log) contiendra des entrées qui ressemblent à :
09:42:15 - Starting install... 09:43:22 - Finished install.
Beaucoup plus propre ! Mais nous pouvons faire mieux.
Ajout de Plus de Fonctionnalités
Améliorons notre fonction de journalisation avec quelques fonctionnalités utiles :
- Chemins de journalisation personnalisés
- Différents niveaux de journalisation (Info, Avertissement, Erreur)
- Date dans le nom de fichier
- Gestion des erreurs
Voici la version améliorée:
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: $_" } }
Cette version améliorée vous offre bien plus de flexibilité. Voici comment l’utiliser:
# 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"
Le fichier journal résultant (log-03-12-2024.txt) ressemblera à ceci:
10:15:22 [Information] - Starting software installation 10:15:23 [Warning] - Config file not found, using defaults 10:15:25 [Error] - Installation failed!
Et dans D:\CustomLogs\log-03-12-2024.txt:
10:15:26 [Information] - Custom path log
Remarquez comment chaque entrée inclut l horodatage, le niveau de journalisation entre crochets, et le message. Ce format structuré facilite l’analyse des journaux et permet d’identifier rapidement les problèmes.
Exemple concret : Script d’installation de logiciel
Mettons notre fonction de journalisation au travail dans un script concret qui installe des logiciels en silence:
# 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"
Le fichier journal résultant ressemblera à ceci:
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
Conseils utiles
Voici quelques bonnes pratiques à suivre lorsque vous utilisez cette fonction de journalisation:
-
Toujours journaliser le début et la fin de votre script – Cela aide à suivre le temps d’exécution du script et son statut d’achèvement.
-
Utiliser des niveaux de journalisation appropriés – Ne marquez pas tout comme une erreur ; utilisez le bon niveau en fonction de la situation :
- Information : Opérations normales
- Avertissement : Problèmes non critiques
- Erreur : Problèmes critiques nécessitant une attention particulière
-
Inclure des détails pertinents – Enregistrer suffisamment d’informations pour comprendre ce qui s’est passé :
# Mauvais Write-Log "Échec de la connexion" # Bon Write-Log "Échec de la connexion au serveur 'SQL01' - délai d'attente après 30 secondes" -Niveau Erreur
-
Nettoyer les anciens journaux – Envisagez d’ajouter une rotation des journaux pour éviter de remplir l’espace disque :
# Supprimer les journaux datant de plus de 30 jours Get-ChildItem -Chemin $CheminJournal -Filtre "*.txt" | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } | Remove-Item
Conclusion
Une bonne fonction de journalisation est essentielle pour tout script PowerShell sérieux. Avec la fonction Write-Log
que nous avons créée, vous disposez désormais d’un moyen flexible et réutilisable d’ajouter une journalisation appropriée à tous vos scripts. N’oubliez pas d’adapter la fonction à vos besoins spécifiques – vous voudrez peut-être ajouter des fonctionnalités telles que :
Rotation des journaux
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... }
Formats de sortie différents (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" } } }
Prise en charge des chemins réseau
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... }
Notifications par e-mail en cas d’erreurs
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: $_" } } }
Le secret est de partir d’une base solide et de construire à partir de là en fonction de vos besoins spécifiques. Ces exemples devraient vous donner un bon point de départ pour étendre la fonction de journalisation de base avec des fonctionnalités plus avancées.
Par exemple, vous pourriez combiner plusieurs de ces fonctionnalités dans une solution de journalisation complète unique :
Write-Log -Message "Critical error in payment processing" ` -Level Error ` -Format CSV ` -NetworkPath "\\\\server\\logs" ` -NotifyOnError "[email protected]","[email protected]" ` -MaxLogFiles 90
Cela permettrait de :
- Enregistrer l’erreur au format CSV
- Le stocker sur un partage réseau
- Envoyer des e-mails à plusieurs destinataires
- Conserver un historique de journal de 90 jours
N’oubliez pas de tester soigneusement, en particulier lors de la mise en place de chemins réseau ou de notifications par e-mail, car ces dépendances externes peuvent affecter la fiabilité de votre script. Bon codage !
Source:
https://adamtheautomator.com/powershell-write-log-tutorial/