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?
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.