Question

I want to monitor a log file which is constantly being added to (every few seconds) over the course of a 2 hour period. I am currently using Get-Content file.txt –Wait which displays the content to the screen and allows me to see what’s being added to the file but I need to take this a step further and actually watch for specific messages and if something I’m looking for in the log file appears, then do something. Initially I used a .net file reader with a for loop as shown below

try {
for(;;) {
    $line = $log_reader.ReadLine()
    if ($line -match "something")
    { 
    Write-Host "we have a match"
    Break
    }

The issue with this however is that it was causing the process that is generating the log file to fall over - it throws an error (because another process is using the log file it’s creating – I thought this was odd because I assumed the .net stream reader would just be ‘reading’ the file). I don’t have any control over the process which is generating the log file so I don’t know what it’s doing exactly (I’m guessing it has the file in read/write mode with some kind of lock which gets upset when I try to read the file using a .net stream reader). Doing a Get-Content on the file doesn’t seem to cause this issue however. The question is, how can I use something like Get-Content (or another process) to monitor the log file but move onto another part of the script if a message I’m looking for in the log appears?

Was it helpful?

Solution

If you constantly want to monitor the log file and catch the desired pattern as soon as it appears:

while(!(Select-String -path 'c:\log.txt' -pattern 'something' -quiet)){};
## when finds the pattern, comes out of the loop and proceed to next part of the script
Write-host 'we have a match'

You may want to change the path of the file to yours.

Though this would work, there will be a lot of processing that your computer have to do, since the while loop is a constant loop. If you can afford to introduce some delay, like if it is OK to find the error 30 sec or whatever is your threshold, after it appeared, then you can consider introducing sleep:

while(!(Select-String -path 'c:\log.txt' -pattern 'something' -quiet)){start-sleep -seconds 30};
## when finds the pattern, comes out of the loop and proceed to next part of the script
Write-host 'we have a match'

You can write a small logic to terminate the script after two hours, otherwise it would become an infinite loop, if 'something' doesn't gets written at all in the log file.

Edit 1:

If you want to print the new lines at the console, you can try manipulating a bit like:

    while(!(Select-String -path 'c:\log.txt' -pattern 'something' -quiet))
     { 
      $a = get-content 'c:\log.txt'
      if(($a.count) -gt $b )
       {
        $a[$b..($a.count)]
       }

      $b = ($a.count) 
      start-sleep -Seconds 30
     }

   ## To print the line containing the pattern when while loop exited 
  (Get-content 'c:\log.txt')[-1] 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top