Automatischer Log-Check via Skript

Schon seit längerem bin ich auf der Suche nach einer Möglichkeit, Logs auf bestimmte Meldungen zu untersuchen. Logs auf einen bestimmten String zu durchsuchen und dann eine Aktion auslösen ist einfach. Die Schwierigkeit besteht darin, das die gewünschte Aktion nur dann ausgelöst wird, wenn der String auch wirklich im Log File vorkommt und nicht dauernd nachdem der String einmal im Log vorkam (Weil immer noch das gesamte Log geparst und der String somit gefunden wird).

Letztlich habe ich begonnen, mich mit Powershell zu beschäftigen und so kam es, dass ich die Lösung auch in dieser Skriptsprache realisiert habe. Diese Lösung möchte ich anbei kurz vorstellen. Es sei darauf hingewiesen, dass es mein „erster Wurf“ ist und sicher noch Raum zur Verbesserung besteht.

Servernamen, Pfade und Co. habe ich in Variablen verpackt, hier verwende ich jedoch fiktive Namen um die Lesbarkeit zu verbessern. Los geht’s:

If (test-path \\path\to\templog\log)
{
write-output "tempolog exist, copy not required"
}
else
{
copy \\path\to\orglog\log \\path\to\templog\log
}

Damit ich jeweils nur die Änderung zum letzten Check überprüfe, kopiere ich das Log vom Server (orglog) an einen anderen Ort (templog). Dieser Schritt ist nur beim ersten Lauf notwendig, oder wenn das „templog“ gelöscht wurde. Dies kann notwendig sein, wenn das „orglog“ neu erstellt wird. Siehe dazu „Limitationen“ weiter unten.

Anschliessend vergleiche ich die beiden Dateien:

$compa = compare
-referenceobject$(get-content \\path\to\orglog\log)
-differenceobject $(get-content  \\path\to\templog\log)
-passthru

In der Variabel $compa ist die Differenz vom „orglog“ zum „templog“ enthalten. Beim ersten Skriptlauf gibt es natürlich noch keine Differenz, bei jedem weiteren Lauf enthält „$compa“ die Differenz zum letzten Lauf. Anschliessend kann den Inhalt der Variabel „$compa“ auf einen String durchsucht werden:
if ($compa | select-string -pattern "Method timed out")
{
...
}

In der geschweiften Klammer kann dann alles mögliche passieren, wie zum Beispiel ein Mail versandt und ein Dienst neu gestartet werden. Damit man beim nächsten Lauf des Skripts auch nur die neuen Einträge (Delta zu diesem Lauf) untersucht, füge ich den Inhalt der Variabel „$compa“ dem „templog“ an:
Add-Content \\path\to\templog\log $compa

Damit das Skript zeigesteuert aufgerufen wird, erstelle ich einen geplanten Task auf einem Windows Server, dabei verwende ich folgenden Aufrufparameter:
C:\path\to\powershell.exe
-nolog -command "&{E:\Path\to\script.ps1}"

Das Ganze ist bei mir seit rund zwei Wochen im Einsatz und funktioniert ganz gut. Jedoch kenne ich bis jetzt zumindest folgende Limitationen:

  • Ich weiss, wann das Log neu erstellt wird. Zu diesem Zeitpunkt lösche ich mein „templog“. Wenn ein neues Log erstellt wird, wenn z.B eine gewisse Grösse erreicht wurde, funktioniert mein Skript nicht.
  • Ich habe einmal erlebt, dass das „templog“ über 100MB gross war und nichts mehr funktioniert hat, weshalb weiss ich bis jetzt nicht.