3

I'm working on a process to start up some services across remote servers, however server 2 can't start up until a message is found in server1 logs, server 3 can't start until same message in server 2, etc.

My question is, is it possible to read the file in a "loop" and not proceed with my initial loop until that message is found (and then move forward)? I was thinking I could do below, however while it does recognize that the string in the log file is found, it just repeats that it found it until the timer built in finishes and then moves forward. So, the process would look like "read this file, if string is found, move forward. If string is not found, wait 30 seconds and rescan the file. If found, move forward, if not found, wait an additional 30 seconds and rescan (I'm fine with a continuous repeat) < do this until string is found. Example: enter image description here

Any advice would be much appreciated as I think I might be approaching this from the wrong angle...

-- I left out the majority of the script prior to this script and only included the If/Else statement as this is where it checks the files.

$SEL = Select-String -Path \\$Server\$RootDir\folder\anotherfolder\A-Log-File.log -Pattern "Switching to status: STARTED"
if ($SEL -ne $null)
{
    Write-Host "FOUND: Switching to status: STARTED" -ForegroundColor Yellow -BackgroundColor DarkGreen
}
else
    {
        Write-Host **** Waiting 60 seconds for cache to build ****
            [int]$Time = 60
            $Lenght = $Time / 100
            For ($Time; $Time -gt 0; $Time--) {
            $min = [int](([string]($Time/60)).split('.')[0])
            $text = " " + $min + " minutes " + ($Time % 60) + " seconds left"
            Write-Progress -Activity "Waiting for Started Message" -Status $Text -PercentComplete ($Time / $Lenght)
            Start-Sleep 1
        $SEL = Select-String -Path \\$Server\$RootDir\folder\anotherfolder\A-Log-File.log -Pattern "Switching to status: STARTED"
        if ($SEL -ne $null)
        {
            Write-Host "FOUND: Switching to status: STARTED" -ForegroundColor Yellow -BackgroundColor DarkGreen
        }
        else
            {
                Write-Host **** A-Log-File.log Log does NOT contain a started message **** -ForegroundColor Red -BackgroundColor Yellow 
                Write-Host **** Investigate further or increase the int-time time on Line 54 to 180 seconds **** -ForegroundColor Red -BackgroundColor Yellow ##This part goes away once action can be taken based on reading contents of the file
            }
                                                }
    }
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
Kazic
  • 47
  • 3

3 Answers3

5

You don't need a loop, just use Get-Content -Wait:

$null = Get-Content "\\$Server\$RootDir\folder\anotherfolder\A-Log-File.log" -Wait |Where-Object { $_ -match 'Switching to status: STARTED' } |Select -First 1

Get-Content -Wait will continue outputting new lines written to the file until it's interrupted - luckily we can use Select -First 1 to stop the pipeline once we observe the string

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • But you would have to stop this manually then, right? – marsze Oct 15 '21 at 13:54
  • 3
    @marsze `Select -First 1` will [stop the pipeline](https://stackoverflow.com/questions/60790273/select-object-first-affects-prior-cmdlet-in-the-pipeline/60791320#60791320) as soon as the string is found :) – Mathias R. Jessen Oct 15 '21 at 14:07
  • 1
    Kudos. Nice solution. Never came across `-Wait` before, still learning new things here.. – marsze Oct 15 '21 at 14:09
  • I didn't even THINK about -Wait, thanks for that! I like this solution for once the script can be automated rather than manually called, tucking it away for future use for sure. Thank you Mathias! – Kazic Oct 15 '21 at 15:13
4

You said "loop" so why aren't you using a loop?


while ($true) {
    # (re)try
    $SEL = Select-String -Path "\\$Server\$RootDir\folder\anotherfolder\A-Log-File.log" -Pattern "Switching to status: STARTED"
    if ($SEL -ne $null)
    {
        Write-Host "FOUND: Switching to status: STARTED" -ForegroundColor Yellow -BackgroundColor DarkGreen
        # exit the loop
        break;
    }
    # wait
    Write-Host "**** Waiting 60 seconds for cache to build ****"
    Start-Sleep 1
}
marsze
  • 15,079
  • 5
  • 45
  • 61
  • "loop", I was drawing a blank on the verbiage for what my "if/else" was called. That said, I do like your offering, seems like I was close but was stuck in my own loop (in my head). I like this for the manually ran process of this script I'm making, especially since I can display to the user what it's waiting on. Thank you very much Marsze! – Kazic Oct 15 '21 at 15:15
0

@marsze, I meant to come back to this and update. I ended up using your suggestion and also wanted to add in that I was able to build in a timer. I wanted to provide the example for anyone that stumbles upon this.

while ($true) {
    # (re)try
    $SEL = Select-String -Path "\\$Server\$SomeRoot\A.Folder\b.folder2\ThisFileToParse.log" -Pattern "Message Here"
    if ($SEL -ne $null)
    {
        Write-Host "FOUND: Message Here" -ForegroundColor Yellow -BackgroundColor DarkGreen
        # exit the loop
        break;
    }
    # wait
    Write-Host "**** File Does NOT contain a Message Here message ****" -ForegroundColor Red -BackgroundColor Yellow 
    Write-Host "**** Waiting 30 seconds, will loop until message is found ****"  -ForegroundColor Red -BackgroundColor Yellow 
    #Start-Sleep 1
    [int]$Time = 30
    $Lenght = $Time / 100
    For ($Time; $Time -gt 0; $Time--) {
    $min = [int](([string]($Time/60)).split('.')[0])
    $text = " " + $min + " minutes " + ($Time % 60) + " seconds left"
    Write-Progress -Activity "Waiting for ThisFileToParse.log to update showing Message Here... " -Status $Text -PercentComplete ($Time / $Lenght)
    Start-Sleep 1
    }
Kazic
  • 47
  • 3