Reputation: 1973
I have a list of log files, these log files get created every day at 00:00:00, so each day gets logged in a seperate log file. 4 Log Files for 4 different reasons get created everyday, and I have to loop over them and select the error messages.
The log files have the following structure:
07.11.2016 12:00:41 Flag: Mandant=1, Modul=V, Pool=5
07.11.2016 12:00:41 Verarbeiten: M1, V, Pool 5, Dok 526198(), DokTyp 3, Skript BU-CO110.FF, Drucker 97
07.11.2016 12:00:41 fataler Fehler SalDocPoolItem_Process(5,): Err-226/VER-Dokument nicht gefunden: 0
07.11.2016 12:00:57 Flag: Mandant=1, Modul=V, Pool=5
07.11.2016 12:00:57 Verarbeiten: M1, V, Pool 5, Dok 526198(), DokTyp 3, Skript BU-CO110.FF, Drucker 97
07.11.2016 12:00:57 fataler Fehler SalDocPoolItem_Process(5,): Err-226/VER-Dokument nicht gefunden: 0
07.11.2016 12:01:13 Flag: Mandant=1, Modul=V, Pool=5
07.11.2016 12:01:13 Verarbeiten: M1, V, Pool 5, Dok 526198(), DokTyp 3, Skript BU-CO110.FF, Drucker 97
07.11.2016 12:01:13 fataler Fehler SalDocPoolItem_Process(5,): Err-226/VER-Dokument nicht gefunden: 0
As you can see theres a message "fataler fehler" on the bottom of each block, so I need to get this whole block into an array, and then send all "fataler Fehler" blocks of all log files together in a simple E-Mail.
Now I basically have the code, but this code either has a mistake, or needs more than 10 minutes to execute, since I ran it 5 minutes before starting to write this question, and it's still not finished.
Goal: Have all the blocks in the $FailArray
Variable
Can you tell me a better way to achieve my goal? I really don't like using get-content
twice because I feel like it's not necessary, I'm sure there's a better solution to this than mine:
# Prepare Array
$FailArray = @()
# Search for Log Files
$a = gci "C:\path" -filter *.log | ? { $_.LastWriteTime -ge (get-date).AddDays('-1') }
# Loop over Log Files
$a | % {
# Are there errors in the log?
$x = get-content $_.FullName | ? { $_ -like "*Fehler*" }
# If there are errors in the block, get the "time stamp" of the Block, like 12:00:57
if ($x) { $y = $x | % { $_.split(' ')[1] } } else { return }
# Search the whole block, depending on the timestamp
$z = get-content $_.FullName | ? { $_ -like "*$y*" }
# Add found blocks to FailArray
$FailArray += $z
}
More: Sometimes, the first message of the block has a timestamp 1 second different from the others like this - is it possible to still get the whole block somehow? (just a nice to have, not necessary)
07.11.2016 12:00:24 Flag: Mandant=1, Modul=V, Pool=5
07.11.2016 12:00:25 Verarbeiten: M1, V, Pool 5, Dok 526198(), DokTyp 3, Skript BU-CO110.FF, Drucker 97
07.11.2016 12:00:25 fataler Fehler SalDocPoolItem_Process(5,): Err-226/VER-Dokument nicht gefunden:
Upvotes: 1
Views: 48
Reputation: 59011
You can use the -context
parameter and select the two lines above your match + the actual match:
$FailArray = gci "C:\path" -filter *.log | ? { $_.LastWriteTime -ge (get-date).AddDays('-1') } | % {
Select-String -Path $_ -Pattern 'fataler Fehler' -Context 2,0 | foreach {$_.Context.PreContext; $_.Line}
}
Upvotes: 3