Wenn Sie PowerShell-Skripte schreiben, die etwas Bedeutendes tun, benötigen Sie ein Protokoll. Egal, ob Sie Software bereitstellen, Dienste verwalten oder Aufgaben automatisieren, es ist entscheidend, eine Aufzeichnung darüber zu haben, was Ihr Skript getan (oder nicht getan) hat. In diesem Tutorial lernen Sie, wie Sie eine einfache, aber effektive PowerShell-Protokollierungsfunktion erstellen.
Voraussetzungen
Wenn Sie diesem Tutorial folgen möchten, stellen Sie sicher, dass Sie folgendes haben:
- Windows 10 oder Windows Server mit PowerShell 5.1 oder PowerShell 7+
- Einen Texteditor (VSCode empfohlen)
- Grundlegendes Verständnis von PowerShell-Funktionen
Das Problem mit der einfachen Protokollierung
Angenommen, Sie schreiben ein Skript, um einige Software lautlos zu installieren. Der grundlegende Ansatz könnte so aussehen:
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."
Dies funktioniert, hat jedoch einige Probleme:
- Keine Zeitstempel
- Wiederholender Code
- Unkonsistentes Protokollierungsformat
- Festgelegter Protokollpfad
Beheben wir diese Probleme, indem wir eine richtige Protokollierungsfunktion erstellen.
Erstellen einer grundlegenden Write-Log-Funktion
Zunächst erstellen wir eine einfache Funktion, die Zeitstempel zu unseren Protokolleinträgen hinzufügt:
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" }
Jetzt können Sie es wie folgt verwenden:
Write-Log -Message "Starting install..." Start-Process -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow Write-Log -Message "Finished install."
Die Protokolldatei (C:\Scripts\script.log) enthält Einträge, die so aussehen:
09:42:15 - Starting install... 09:43:22 - Finished install.
Viel übersichtlicher! Aber wir können es noch besser machen.
Hinzufügen weiterer Funktionalitäten
Erweitern wir unsere Protokollierungsfunktion um einige nützliche Funktionen:
- Benutzerdefinierte Protokollpfade
- Verschiedene Protokollebene (Info, Warnung, Fehler)
- Datum im Dateinamen
- Fehlerbehandlung
Hier ist die verbesserte Version:
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: $_" } }
Diese erweiterte Version bietet Ihnen viel mehr Flexibilität. So verwenden Sie sie:
# 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"
Die resultierende Protokolldatei (log-03-12-2024.txt) wird so aussehen:
10:15:22 [Information] - Starting software installation 10:15:23 [Warning] - Config file not found, using defaults 10:15:25 [Error] - Installation failed!
Und in D:\CustomLogs\log-03-12-2024.txt:
10:15:26 [Information] - Custom path log
Beachten Sie, wie jeder Eintrag den Zeitstempel, die Protokollebene in Klammern und die Nachricht enthält. Dieses strukturierte Format erleichtert das Parsen von Protokollen und das schnelle Erkennen von Problemen.
Echtweltbeispiel: Softwareinstallationsskript
Lassen Sie uns unsere Protokollierungsfunktion in einem echten Skript verwenden, das Software im Stillen installiert:
# 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"
Die resultierende Protokolldatei wird ungefähr so aussehen:
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
Nützliche Tipps
Hier sind einige bewährte Verfahren bei der Verwendung dieser Protokollierungsfunktion:
-
Protokollieren Sie immer den Beginn und das Ende Ihres Skripts – Dies hilft, die Ausführungszeit des Skripts und den Abschlussstatus zu verfolgen.
-
Verwenden Sie geeignete Protokollebene – Markieren Sie nicht alles als Fehler; verwenden Sie die richtige Ebene für die Situation:
- Information: Normale Vorgänge
- Warnung: Nicht kritische Probleme
- Fehler: Kritische Probleme, die Aufmerksamkeit erfordern
-
Relevante Details einbeziehen – Protokollieren Sie ausreichend Informationen, um zu verstehen, was passiert ist:
# Schlecht Write-Log "Verbindung fehlgeschlagen" # Gut Write-Log "Verbindung mit Server 'SQL01' fehlgeschlagen - Timeout nach 30 Sekunden" -Level Fehler
-
Alte Protokolle bereinigen – Erwägen Sie die Hinzufügung von Protokollrotation, um ein Überfüllen des Speicherplatzes zu verhindern:
# Löschen von Protokollen, die älter als 30 Tage sind Get-ChildItem -Path $LogFilePath -Filter "*.txt" | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } | Remove-Item
Abschluss
Eine gute Protokollierungsfunktion ist für jedes ernsthafte PowerShell-Skript unerlässlich. Mit der von uns erstellten Write-Log
-Funktion haben Sie nun eine flexible und wiederverwendbare Möglichkeit, ordnungsgemäße Protokollierung zu all Ihren Skripten hinzuzufügen. Denken Sie daran, die Funktion an Ihre spezifischen Anforderungen anzupassen – Sie könnten Funktionen wie hinzufügen wollen:
Protokollrotation
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... }
Verschiedene Ausgabeformate (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" } } }
Unterstützung von Netzwerkpfaden
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... }
E-Mail-Benachrichtigungen für Fehler
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: $_" } } }
Der Schlüssel ist, mit einer soliden Grundlage zu beginnen und basierend auf Ihren spezifischen Anforderungen darauf aufzubauen. Diese Beispiele sollten Ihnen einen guten Ausgangspunkt bieten, um die grundlegende Protokollierungsfunktion um fortgeschrittenere Funktionen zu erweitern.
Zum Beispiel könnten Sie mehrere dieser Funktionen in einer einzigen, umfassenden Protokollierungslösung kombinieren:
Write-Log -Message "Critical error in payment processing" ` -Level Error ` -Format CSV ` -NetworkPath "\\\\server\\logs" ` -NotifyOnError "[email protected]","[email protected]" ` -MaxLogFiles 90
Dies würde:
- Den Fehler im CSV-Format protokollieren
- Auf einem Netzlaufwerk speichern
- Mehrere Empfänger per E-Mail benachrichtigen
- 90 Tage Protokollhistorie aufbewahren
Denken Sie daran, gründlich zu testen, insbesondere beim Implementieren von Netzwerkpfaden oder E-Mail-Benachrichtigungen, da diese externen Abhängigkeiten die Zuverlässigkeit Ihres Skripts beeinträchtigen können. Viel Spaß beim Skripten!
Source:
https://adamtheautomator.com/powershell-write-log-tutorial/