# Servers file with one server per line
$Servers = Get-Content -Path "C:\Temp\Scripts\Servers.txt"
# Files to search with one file PATH per line
$SearchFiles = Get-Content -Path "C:\Temp\Scripts\SearchFiles.txt"
# Log file
$LogFile = "C:\Temp\Scripts\Logger.txt"
$Servers | ForEach {
If (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
$UNCBase = "\\$_\"
$SearchFiles | ForEach {
$RemoteFilePath = $UNCBase + $_.Replace(':', '$')
If (Test-Path -Path $RemoteFilePath) {
Get-Content $RemoteFilePath | Where { $_ -match “ERROR” } | Out-File $LogFile -Append
}
Else {
Write-Output "$RemoteFilePath cannot be found"
}
}
}
Else {
Write-Output "$_ is offline"
}
}
# Servers file with one server per line
$Servers = Get-Content -Path "C:\Temp\Scripts\Servers.txt"
# Files to search with one file PATH per line
$SearchFiles = Get-Content -Path "C:\Temp\Scripts\SearchFiles.txt"
# Log share that the remote jobs will have access to
$LogShare = "\\SERVER\PublicShare\Logs"
$RemoteFunction = {
Function CheckFile {
Param (
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
[String]$FilePath,
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
[String]$LogPath
)
#Write-Output "Reading $FilePath and logging to $LogPath" | Out-File -Append $LogPath
If (Test-Path -Path $FilePath) {
Get-Content $FilePath -Wait | Select-String "Error" | Select -Expand Line | Out-File -Append $LogPath
}
}
}
ForEach ($Server In $Servers) {
ForEach ($FileSpec In $SearchFiles) {
$LogFile = $LogShare + "\" + $Server + "_" + ($FileSpec.Split("\") | Select -Last 1) + "_ERRORS.txt"
Write-Output $FileSpec
Write-Output $LogFile
Start-Job -ScriptBlock {CheckFile $args[0] $args[1]} -ArgumentList @($FileSpec, $LogFile) -InitializationScript $RemoteFunction
}
}
You can decide whether you allow each file to be appended individually, or output collected and then appended.
Open in new window
But that is inefficient, as we need a polling loop now. Allowing each job to do the work seems to be better, but you get the risk to have multiple processes writing to the same file at the same time, resulting in garbled content. (The following code also uses a loop to go thru paths)Open in new window