Lesson Learned #406:Monitoring Resource Usage and Open Ports with PowerShell Script

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Community Hub.

In today's fast-paced digital landscape, it is crucial for organizations to efficiently monitor and manage their infrastructure's resource utilization. High resource consumption or misconfigured open ports can lead to performance issues, downtimes, and security vulnerabilities. To address these concerns, we present a PowerShell script that provides valuable insights into the resource usage and open ports of the environment where an application is running. This script allows administrators to identify potential bottlenecks and optimize their systems for better performance and security.

 

Understanding the PowerShell Script:

 

The PowerShell script is designed to gather real-time data on CPU, memory, I/O usage, network interface status, open ports, and running processes. The data is collected periodically and stored in separate CSV files for further analysis.

 

Duration and Data Collection Interval:

 

The script is equipped with a customizable duration, allowing users to define how long the monitoring process should run. For instance, setting the duration to 20 minutes will continuously collect data for the specified timeframe.

 

Data Collected and Their Significance:

  1. General Usage Data:

    • CPU Usage: Monitors the CPU load percentage to identify potential performance bottlenecks.
    • Memory Usage: Tracks the percentage of used memory to assess memory requirements and prevent memory-related issues.
  2. Network Usage Data:

    • Interface Status: Records the status (Up/Down) of all network interfaces, offering insights into connectivity health.
    • Description and Name: Provides details about each network interface, facilitating identification and troubleshooting.
  3. Ports Usage Data:

    • Protocol: Logs the protocol used by each open port to ascertain potential security risks.
    • Local and Foreign Addresses: Captures IP addresses and port numbers to identify incoming and outgoing connections.
    • State: Reveals the state of each port (Listening, Established, etc.), aiding in identifying active connections.
    • Process ID and Application Name: Associates open ports with corresponding processes, helping in resource allocation and security analysis.
  4. Processes Usage Data:

    • Process Name and ID: Lists all running processes along with their unique IDs for process identification.
    • CPU, Memory, and Virtual Memory Usage: Provides resource consumption statistics for each running process.
    • Handles: Indicates the number of handles used by each process, which can help identify resource leaks.

 

DNS Resolution Verification:

 

The script also performs DNS resolution verification for a specified list of server names. This ensures that DNS records are correctly resolving, preventing potential connectivity issues.

 

Conclusion:

With this comprehensive PowerShell script, administrators can gain deeper insights into their infrastructure's performance and resource utilization. By monitoring CPU, memory, I/O, network interfaces, open ports, and running processes, organizations can identify and address potential issues proactively. Armed with this knowledge, IT teams can optimize their systems for maximum efficiency and security, ensuring smooth and uninterrupted operations.

 

I hope this article provides valuable information about the PowerShell script as an example and its capabilities for monitoring resource usage and open ports. 

 

# Define the duration for script execution (in minutes) $durationMinutes = 20 $intervalSeconds = 120 $endTime = (Get-Date).AddMinutes($durationMinutes) # User-specified output path $outputPath = "C:\temp\OutputFolder" # Replace with the desired output folder path # List of server names for DNS resolution verification $serverNames = @( "myserverexample.database.windows.net", "example.com", "nonexistentserver12345.com" ) # Function to log messages to console and a log file function Log-Message { param ( [string]$Message, [string]$timestamp ) Write-Output "$timestamp - $Message" $logFilePath = Join-Path -Path $outputPath -ChildPath "ScriptLog.log" "$timestamp - $Message" | Out-File -FilePath $logFilePath -Append } # Function to gather general CPU, memory, and I/O usage function Get-GeneralUsageData { param ( [string]$timestamp ) $cpuUsage = Get-WmiObject -Class Win32_Processor | Select-Object -ExpandProperty LoadPercentage $memoryUsage = Get-WmiObject -Class Win32_OperatingSystem | Select-Object -Property @{Name = "MemoryUsage(%)"; Expression = { [math]::Round(($_.TotalVisibleMemorySize - $_.FreePhysicalMemory) / $_.TotalVisibleMemorySize * 100, 2) } } $usageData = [PSCustomObject]@{ Timestamp = $timestamp CPUUsage = $cpuUsage MemoryUsage = $memoryUsage."MemoryUsage(%)" } return $usageData } # Function to gather network interface status, description, and name for UP adapters function Get-NetworkUsageData { param ( [string]$timestamp ) $networkInfo = Get-NetAdapter | Where-Object { $_.Status -eq "Up" } $networkData = foreach ($adapter in $networkInfo) { $status = $adapter.Status $description = $adapter.InterfaceDescription [PSCustomObject]@{ Timestamp = $timestamp Status = $status Description = $description } } return $networkData } # Function to gather ports usage data function Get-PortsUsageData { param ( [string]$timestamp ) $netstatOutput = netstat -ano $portsData = $netstatOutput | ForEach-Object { $line = $_.Trim() -replace '\s+', ' ' $parts = $line -split ' ' $protocol = $parts[0] $localAddress = $parts[1] $foreignAddress = $parts[2] $state = $parts[3] $processId = $parts[-1] if (-not [string]::IsNullOrWhiteSpace($processId) -and $processId -match '^\d+$') { $process = Get-Process -Id $processId -ErrorAction SilentlyContinue if ($process) { $appName = $process.Name } else { $appName = "N/A" } } else { $processId = "N/A" $appName = "N/A" } [PSCustomObject]@{ Timestamp = $timestamp Protocol = $protocol LocalAddress = $localAddress ForeignAddress = $foreignAddress State = $state ProcessId = $processId ApplicationName = $appName } } return $portsData } # Function to gather processes usage data function Get-ProcessesUsageData { param ( [string]$timestamp ) $processes = Get-Process $processesData = foreach ($process in $processes) { $processName = $process.Name $processId = $process.Id $cpuUsage = $process.CPU $memoryUsage = $process.WorkingSet $virtualMemory = $process.VirtualMemorySize $handles = $process.Handles [PSCustomObject]@{ Timestamp = $timestamp ProcessName = $processName ProcessId = $processId CPUUsage = $cpuUsage MemoryUsage = $memoryUsage VirtualMemory = $virtualMemory Handles = $handles } } return $processesData } # Function to test DNS resolution for a list of server names function Test-DnsResolution { param ( [string]$timestamp ) $dnsResolutionData = foreach ($server in $serverNames) { $startTime = Get-Date try { $ipAddress = [System.Net.Dns]::GetHostAddresses($server) | Select-Object -ExpandProperty IPAddressToString $endTime = Get-Date $timeTaken = ($endTime - $startTime).TotalMilliseconds $result = "Resolved" } catch { $ipAddress = "N/A" $timeTaken = "N/A" $result = "Failed to resolve" } [PSCustomObject]@{ Timestamp = $timestamp ServerName = $server IPAddress = $ipAddress TimeTakenMilliseconds = $timeTaken Result = $result } } return $dnsResolutionData } # Function to save data to a CSV file function Save-DataToCsv { param( [Parameter(Mandatory = $true)] [string]$FilePath, [Parameter(Mandatory = $true)] [array]$Data ) $logFilePath = Join-Path -Path $outputPath -ChildPath $FilePath $Data | Export-Csv -Path $logFilePath -NoTypeInformation -Append } # Create the output folder if it doesn't exist if (-Not (Test-Path -Path $outputPath -PathType Container)) { New-Item -ItemType Directory -Path $outputPath | Out-Null } # Infinite loop for continuous monitoring until the specified duration while ((Get-Date) -lt $endTime) { $timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") Log-Message "Starting data collection iteration..." -timestamp $timestamp # Gather data Log-Message "Gathering general usage data..." -timestamp $timestamp $generalUsageData = Get-GeneralUsageData -timestamp $timestamp Log-Message "Gathering network usage data..." -timestamp $timestamp $networkUsageData = Get-NetworkUsageData -timestamp $timestamp Log-Message "Gathering ports usage data..." -timestamp $timestamp $portsUsageData = Get-PortsUsageData -timestamp $timestamp Log-Message "Gathering processes usage data..." -timestamp $timestamp $processesUsageData = Get-ProcessesUsageData -timestamp $timestamp Log-Message "Performing DNS resolution verification..." -timestamp $timestamp $dnsResolutionData = Test-DnsResolution -timestamp $timestamp # Save data to CSV Save-DataToCsv -FilePath "GeneralUsage.csv" -Data $generalUsageData Save-DataToCsv -FilePath "NetworkUsage.csv" -Data $networkUsageData Save-DataToCsv -FilePath "PortsUsage.csv" -Data $portsUsageData Save-DataToCsv -FilePath "ProcessesUsage.csv" -Data $processesUsageData Save-DataToCsv -FilePath "DnsResolution.csv" -Data $dnsResolutionData Log-Message "Data collection iteration completed." -timestamp $timestamp # Wait for the interval before the next iteration Start-Sleep -Seconds $intervalSeconds }

 

Enjoy!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.