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:
-
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.
-
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.
-
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.
-
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!