Search code examples
powershellconcurrencystart-job

Job quits unexpectedly


I would like to use Start-Job to simultaneously monitor (tail) more than one log file using Get-Content file -Wait -Last 1 (-Last 1 to avoid opening the whole log).

Running gc $file -Last 1 -Wait allows to tail only one file. Wrapping that up in a Start-Job -Scriptblock quits the job immediately.

I had something like this in mind.

Start-Job -Name srv1 -ScriptBlock {Get-Content "\\srv1\$log" -Wait -Last 1} | Select-String "matching some text only" | Out-File D:\autogrep.log}
Start-Job -Name srv2 -ScriptBlock {Get-Content "\\srv2\$log" -Wait -Last 1} | Select-String "matching some text only" | Out-File D:\autogrep.log}
Start-Job -Name srv3 -ScriptBlock {Get-Content "\\srv3\$log" -Wait -Last 1} | Select-String "matching some text only" | Out-File D:\autogrep.log}
Start-Job -Name srv4 -ScriptBlock {Get-Content "\\srv4\$log" -Wait -Last 1} | Select-String "matching some text only" | Out-File D:\autogrep.log}
Start-Job -Name srv5 -ScriptBlock {Get-Content "\\srv5\$log" -Wait -Last 1} | Select-String "matching some text only" | Out-File D:\autogrep.log}

Any suggestions how to solve this?


Solution

  • Simultaneously writing to the same output file from different jobs is going to create a race condition unless you have a scheduler in place to coordinate write access. Also, if you want to read a log from an UNC path you need to provide the path as \\server\share\file.

    Try something like this:

    $servers = 'srv1', 'srv2', 'srv3', 'srv4', 'srv5'
    $jobs    = @()
    
    $servers | ForEach-Object {
      $jobs += Start-Job -Name $_ -ScriptBlock {
        Param($server, $log)
        Get-Content "\\$server\share\$log" -Wait -Last 1
      } -ArgumentList $_, 'your.log'
    }
    
    while ($jobs.State -contains 'Running') {
      $jobs | Where-Object { $_.hasMoreData } |
        Receive-Job |
        Select-String 'matching some text only' |
        Out-File 'D:\autogrep.log' -Append
      Start-Sleep -Milliseconds 100
    }
    

    Note that if you're still using PowerShell v2 you need to replace $jobs.State with @($jobs | Select-Object -Expand State), because PowerShell doesn't automatically unroll arrays on property access prior to v3.