Peter Hinchley

Learning in Public

✪ Collect Logs from Multiple Servers with PowerShell

The code in this post is rather simplistic, and very specific to a particular task, but some of the concepts may prove useful to others.

The requirement was to copy a specific log file from a large number of servers to a central management server, search the copied logs for a specific error code, and write matched entries - using a prefix to denote the server of origin - to a consolidated "results" file.

A few points of interest:

Here is the code:

# An array of servers to be queried.
$servers = @("abc.local.net", "xyz.local.net")

# The local path (on each remote server) of the log file to be collected.
$sourcePath = "c:\logs\log.txt"

# The target folder (on the local management server) into which the log files will be collected.
$targetPath = "c:\archive"

# The path (on the local management server) to the file that will hold the matched log entries.
$searchResultPath = "C:\logs\results.txt"

# The search term.
$searchTerm = "critical error"

# The number of lines searched at the end of each log.
$tail = 100

# Do not change the code below this point.

# Substitute the "admin" share for the local path.
$sourceSharePath = $sourcePath.Replace(':', '$')

# Get the target file name.
$targetName = $sourcePath.split('\')[-1] 

# Iterate through the list of servers.
$servers | %{
  $server = $_

  # Get the UNC path to the source log.
  $sourceUncPath = "\\$server\$sourceSharePath"

  # Add the server name to the target path.
  # e.g. log.txt => log.server.txt
  $uniqueTargetName = $targetName.Replace(".", "-$server.")
  $uniqueTargetPath = "$targetPath\$uniqueTargetName"

  # Check if the server is online.
  if (Test-Connection $server -Count 1 -Quiet) {
    Write-Host "$server is online."

    # Check if the source is accessible.
    if (Test-Path $sourceUncPath) {
      Write-Host "`tConnected to $server."

      # Copy the source log to the target folder.
      Write-Host "`tCopying $sourceUncPath to $uniqueTargetPath."
      Copy-Item $sourceUncPath $uniqueTargetPath -Force

      # Seach the tail of the copied log for the pattern.
      Get-Content $uniqueTargetPath -Tail $tail | Select-String $searchTerm -AllMatches | %{
        # Prefix the matched content with the name of the source server and add to the results.
        "$($server): $_" | Out-File -Append $searchResultPath
      }
    } else {
      Write-Host "`tCould not connect to $server." -foregroundcolor magenta
    }
  } else {
    Write-Host "$server is offline" -foregroundcolor magenta
  }
}