Einfaches Logging für PowerShell-Skripte
Lange und komplexe PowerShell-Skripte werden schnell unübersichtlich und man verliert den Überblick, wo das Skript gerade steht und was aktuell abgearbeitet wird. Aus diesem Grund solltet ihr in jedem Skript bereits von Anfang an eine einfache Log-Funktionalität einbauen. Dies ist in vielen Fällen schneller und einfacher zu realisieren, als das Logging später aufwändig nachzurüsten. Vor allem bei Skripten, welche kritische Daten schreiben, ist das Logging im Nachhinein oftmals ein Segen. Beispielsweise wenn euer PowerShell-Skript Daten im AD ändert und im Nachgang einige Änderungen rückgängig gemacht werden müssen.
Daher habe ich eine kleine Funktion geschrieben, welche ich nahezu am Anfang jedes PowerShell-Skripts einbinde. Die Ausgabe erfolgt sowohl in der Konsole als auch in einer Log-Datei. Neben dem aktuellen Datum und der Uhrzeit ermöglicht die Log-Funktion zudem die Definition von verschiedenen Log-Leveln.
Das Skript steht auch als Download zur Verfügung.
$path = "C:\Temp"
$date = get-date -format "yyyy-MM-dd-HH-mm"
$file = ("Log_" + $date + ".log")
$logfile = $path + "\" + $file
function Write-Log([string]$logtext, [int]$level=0)
{
$logdate = get-date -format "yyyy-MM-dd HH:mm:ss"
if($level -eq 0)
{
$logtext = "[INFO] " + $logtext
$text = "["+$logdate+"] - " + $logtext
Write-Host $text
}
if($level -eq 1)
{
$logtext = "[WARNING] " + $logtext
$text = "["+$logdate+"] - " + $logtext
Write-Host $text -ForegroundColor Yellow
}
if($level -eq 2)
{
$logtext = "[ERROR] " + $logtext
$text = "["+$logdate+"] - " + $logtext
Write-Host $text -ForegroundColor Red
}
$text >> $logfile
}
# log something
Write-Log "this is a simple log test"
# create warning log entry
Write-Log "this is a simple log test" 2
# use more than simple variables in a string
$cmds = get-command
Write-Log "there are $($cmds.count) commands available"
Sie sehen gerade einen Platzhalterinhalt von X. Um auf den eigentlichen Inhalt zuzugreifen, klicken Sie auf die Schaltfläche unten. Bitte beachten Sie, dass dabei Daten an Drittanbieter weitergegeben werden.
Mehr Informationen
Hallo!
Ich bin auf dein Script gestoßen, was mir auch schon mal sehr geholfen hat.
Ein Problem habe ich allerdings. Per Invoke-command lasse ich eine Funktion auf einem remote-System laufen. Das an sich klappt alles, nur wenn ich meine Write-Host durch dein Write-Log ersetze meckert er, dass er “Write-Log” nicht kennt, da es vermutlich in dem Invoke-Command-Kontext nicht bekannt ist.
Hast du eine Idee, wie sich das umgehen lässt?
Vielen Dank
Jonas
So müsste das klappen:
Alternativ kannst du die Funktion auch einfach als Datei kopieren und ausführen lassen:
Danke dafür!
Ich fürchte, dass mein Problem etwas komplizierter ist. Bin leider noch kein PowerShell-Profi, daher weiß ich nicht, ob das überhaupt so machbar ist.
Ich habe eine Funktion (TestServer), welche entweder lokal ausgeführt wird, oder remote per invoke-command, so wie du angegeben hast mit ${funcion:TestServer}.
In der Funktion TestServer sind deine Write-Logs drin, z.B.:
Write-Log 9 “Edition: $((Get-ItemProperty “HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$p\Setup”).Edition)” (etwas angepasst, habe 2 LogLevel hinzugefügt und die parameter umgedreht).
Wenn ich jetzt die Funktion Write-Log IN die Funktion TestServer schiebe (also function in function), klappt es, ich bekomme es allerdings nur in der Ausgabe zu sehen, es wird nicht ins Log geschrieben (vermutlich, weil es irgendwo ins Log auf dem Remote-System geht). Ein Get-Location in dem Skript welches per Invoke-Command ausgeführt wird gibt mir an, dass der aktuelle Pfad auf dem Remote-System C:\users\USERNAME\documents ist. Dort finden sich allerdings keinerlei Logs.
Ein wie von dir vorgeschlagener Aufruf scheint mir nicht praktikabel, da ich denselben Code für local und remote Server habe (einmal direkt, einmal wie gesagt per invoke-command).
Aber vielleicht muss ich mir was anderes überlegen und zwei verschiedene funktionen für local und remote bauen (was ich erst so hatte, dann aber um doppelten code zu vermeiden umgebaut habe)
Ich habe glaube ich eine Lösung gefunden:
> function TestServer {
>>>>function Write-Log { … }
> Write-Log 1 “testausgabe”
>}
Invoke-Command -ComputerName $sqlserver -ScriptBlock ${Function:TestServer} | Tee-Object -FilePath $logfile -Append