别再傻傻看任务管理器了!用PowerShell Get-WmiObject精准揪出服务器内存‘吃大户’

张开发
2026/4/21 9:16:26 15 分钟阅读

分享文章

别再傻傻看任务管理器了!用PowerShell Get-WmiObject精准揪出服务器内存‘吃大户’
服务器内存排查实战用PowerShell精准定位资源占用大户当服务器突然变得迟缓响应时间延长甚至触发性能告警时大多数Windows管理员的第一反应是打开任务管理器查看内存占用情况。然而任务管理器提供的信息往往过于表面化难以快速定位问题的根源。本文将介绍如何利用PowerShell的Get-WmiObject命令深入分析服务器内存使用情况精准识别那些吃内存的进程。1. 为什么任务管理器不够用任务管理器是Windows系统中最常用的性能监控工具之一但它存在几个明显的局限性缺乏百分比数据任务管理器显示的是内存占用的绝对值如MB或GB但无法直观展示每个进程占用总内存的比例远程监控困难对于多台服务器的集中管理需要逐台登录查看效率低下历史数据缺失无法查看一段时间内的内存使用趋势只能看到当前瞬间的状态分析维度单一难以对内存使用情况进行多维度统计和排序相比之下PowerShell提供了更强大的内存分析能力# 简单查看前10个内存占用进程 Get-Process | Sort-Object WS -Descending | Select-Object -First 10这个基础命令已经比任务管理器提供了更多的灵活性但我们可以做得更好。2. 深入内存分析Get-WmiObject的强大功能WMIWindows Management Instrumentation是Windows系统管理的核心基础设施通过PowerShell的Get-WmiObject命令我们可以获取比常规方法更详细的系统信息。2.1 获取完整的内存使用情况要全面了解服务器的内存状况我们需要几个关键数据总物理内存系统安装的实际内存容量可用物理内存当前未被使用的内存量各进程内存占用每个运行中的程序使用的内存量以下脚本可以获取这些关键指标# 获取操作系统内存信息 $os Get-WmiObject Win32_OperatingSystem $totalMemory $os.TotalVisibleMemorySize / 1MB $freeMemory $os.FreePhysicalMemory / 1MB $usedMemory $totalMemory - $freeMemory $memoryUsagePercent ($usedMemory / $totalMemory) * 100 Write-Host 内存使用情况 Write-Host 总内存: $($totalMemory.ToString(N2)) MB Write-Host 可用内存: $($freeMemory.ToString(N2)) MB Write-Host 已用内存: $($usedMemory.ToString(N2)) MB Write-Host 内存使用率: $($memoryUsagePercent.ToString(N2))%2.2 识别内存占用大户单纯知道总内存使用情况还不够我们需要找出具体是哪些进程消耗了大量内存。以下脚本可以列出内存占用最高的进程并计算它们占总内存的百分比# 获取内存占用前10的进程及其百分比 $processes Get-WmiObject Win32_Process | Sort-Object -Property WS -Descending | Select-Object -First 10 foreach ($process in $processes) { $processMemoryMB [math]::Round($process.WS / 1MB, 2) $processMemoryPercent [math]::Round(($process.WS / $os.TotalVisibleMemorySize) * 100, 2) Write-Host 进程: $($process.Name) Write-Host PID: $($process.ProcessId) Write-Host 内存占用: $processMemoryMB MB ($processMemoryPercent%) Write-Host ------------------------ }这个脚本的输出比任务管理器提供的信息更有价值因为它不仅显示了内存占用的绝对值还计算了相对于总内存的百分比帮助我们更准确地评估每个进程的影响。3. 高级技巧远程监控与批量分析对于管理多台服务器的IT人员来说能够远程检查内存使用情况是极大的效率提升。PowerShell的Get-WmiObject天然支持远程查询功能。3.1 单台远程服务器检查要检查远程服务器的内存使用情况只需添加-ComputerName参数$remoteComputer SERVER01 $os Get-WmiObject Win32_OperatingSystem -ComputerName $remoteComputer $processes Get-WmiObject Win32_Process -ComputerName $remoteComputer | Sort-Object -Property WS -Descending | Select-Object -First 5 # 显示远程服务器内存概况 Write-Host 远程服务器 $remoteComputer 内存使用率: $([math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / $os.TotalVisibleMemorySize * 100, 2))% # 显示内存占用前5的进程 $processes | ForEach-Object { $memMB [math]::Round($_.WS / 1MB, 2) $memPercent [math]::Round(($_.WS / $os.TotalVisibleMemorySize) * 100, 2) Write-Host $($_.Name) - $memMB MB ($memPercent%) }3.2 批量检查多台服务器对于需要监控多台服务器的情况我们可以将服务器列表存储在数组中然后循环检查$servers (SERVER01, SERVER02, SERVER03, WEB01, DB01) foreach ($server in $servers) { try { $os Get-WmiObject Win32_OperatingSystem -ComputerName $server -ErrorAction Stop $usagePercent [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / $os.TotalVisibleMemorySize * 100, 2) Write-Host 服务器: $server Write-Host 内存使用率: $usagePercent% if ($usagePercent -gt 90) { Write-Host 警告: 内存使用过高! -ForegroundColor Red # 获取内存占用前3的进程 $topProcesses Get-WmiObject Win32_Process -ComputerName $server | Sort-Object -Property WS -Descending | Select-Object -First 3 $topProcesses | ForEach-Object { $memMB [math]::Round($_.WS / 1MB, 2) Write-Host $($_.Name) - $memMB MB } } Write-Host ------------------------ } catch { Write-Host 无法连接到服务器 $server : $_ -ForegroundColor Yellow } }这个脚本会检查列表中的所有服务器标记出内存使用率超过90%的机器并显示这些服务器上内存占用最高的3个进程。4. 实战案例解决内存泄漏问题让我们通过一个实际案例来看看如何应用这些技术解决现实中的内存问题。4.1 问题描述假设我们有一台运行着关键业务应用的服务器最近频繁出现性能下降的情况。任务管理器显示内存使用量很高但无法确定具体原因。4.2 调查步骤首先我们运行完整的内存分析脚本# 全面内存分析脚本 function Get-MemoryAnalysis { param( [string]$ComputerName $env:COMPUTERNAME ) $os Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName $totalMB $os.TotalVisibleMemorySize / 1MB $freeMB $os.FreePhysicalMemory / 1MB $usedMB $totalMB - $freeMB $percentUsed ($usedMB / $totalMB) * 100 $processes Get-WmiObject Win32_Process -ComputerName $ComputerName | Sort-Object -Property WS -Descending | Select-Object -First 10 # 创建自定义对象输出 $output [PSCustomObject]{ ComputerName $ComputerName TotalMemoryGB [math]::Round($totalMB / 1024, 2) UsedMemoryGB [math]::Round($usedMB / 1024, 2) MemoryUsagePercent [math]::Round($percentUsed, 2) TopProcesses $processes | ForEach-Object { [PSCustomObject]{ Name $_.Name PID $_.ProcessId MemoryMB [math]::Round($_.WS / 1MB, 2) MemoryPercent [math]::Round(($_.WS / $os.TotalVisibleMemorySize) * 100, 2) } } } return $output } # 执行分析 $analysis Get-MemoryAnalysis $analysis4.3 分析结果假设脚本输出显示总内存32 GB已用内存30.5 GB (95.3%)内存占用前3的进程CustomApp.exe - 12.5 GB (39.1%)sqlservr.exe - 8.2 GB (25.6%)chrome.exe - 3.1 GB (9.7%)4.4 问题诊断从数据可以看出CustomApp.exe占用了异常高的内存39.1%这很可能是内存泄漏的迹象SQL Server的内存使用虽然较高但在预期范围内Chrome浏览器在服务器上运行且占用大量内存这不符合服务器最佳实践4.5 解决方案基于分析结果我们采取以下措施重启CustomApp服务立即缓解内存压力联系开发团队报告CustomApp的内存泄漏问题移除不必要的浏览器从服务器上卸载Chrome防止非必要应用占用资源设置监控警报创建定期检查内存使用情况的计划任务在内存使用超过85%时发出警报# 示例创建内存监控计划任务 $action New-ScheduledTaskAction -Execute PowerShell.exe -Argument -File C:\Scripts\MemoryMonitor.ps1 $trigger New-ScheduledTaskTrigger -Daily -At 9am Register-ScheduledTask -TaskName Memory Usage Monitor -Action $action -Trigger $trigger -User SYSTEM5. 优化与自动化为了持续监控服务器内存健康状态我们可以将上述技术转化为自动化解决方案。5.1 定期内存检查脚本创建一个脚本定期运行并将结果记录到日志文件中# MemoryMonitor.ps1 $logPath C:\Logs\MemoryUsage_$(Get-Date -Format yyyyMMdd).csv $servers (SERVER01, SERVER02, DB01) $results foreach ($server in $servers) { try { $os Get-WmiObject Win32_OperatingSystem -ComputerName $server -ErrorAction Stop $percentUsed [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / $os.TotalVisibleMemorySize * 100, 2) [PSCustomObject]{ Timestamp Get-Date -Format yyyy-MM-dd HH:mm:ss Server $server MemoryUsagePercent $percentUsed Status if ($percentUsed -gt 85) { Warning } else { Normal } } } catch { [PSCustomObject]{ Timestamp Get-Date -Format yyyy-MM-dd HH:mm:ss Server $server MemoryUsagePercent $null Status Error: $_ } } } # 记录到CSV文件 $results | Export-Csv -Path $logPath -Append -NoTypeInformation # 如果有服务器内存使用过高发送邮件警报 $warningServers $results | Where-Object { $_.Status -eq Warning } if ($warningServers) { $body $warningServers | ConvertTo-Html | Out-String Send-MailMessage -From alertscompany.com -To it-teamcompany.com -Subject High Memory Usage Alert -Body $body -BodyAsHtml -SmtpServer mail.company.com }5.2 内存趋势分析收集一段时间的内存使用数据后我们可以分析内存使用趋势# 分析过去7天的内存日志 $logs Get-ChildItem C:\Logs\MemoryUsage_*.csv | Select-Object -Last 7 | Import-Csv # 按服务器分组计算平均内存使用率 $stats $logs | Group-Object Server | ForEach-Object { $avg $_.Group | Measure-Object -Property MemoryUsagePercent -Average | Select-Object -ExpandProperty Average [PSCustomObject]{ Server $_.Name AverageUsage [math]::Round($avg, 2) MaxUsage ($_.Group | Measure-Object -Property MemoryUsagePercent -Maximum).Maximum WarningCount ($_.Group | Where-Object { $_.Status -eq Warning }).Count } } # 显示统计结果 $stats | Sort-Object AverageUsage -Descending | Format-Table -AutoSize5.3 高级内存分析函数为了更方便地进行内存分析我们可以创建一个高级函数封装常用的内存检查功能function Get-ServerMemoryHealth { param( [Parameter(Mandatory$true)] [string[]]$ComputerName, [int]$TopProcessCount 5, [int]$WarningThreshold 85, [int]$CriticalThreshold 95 ) foreach ($computer in $ComputerName) { try { # 获取操作系统内存信息 $os Get-WmiObject Win32_OperatingSystem -ComputerName $computer -ErrorAction Stop $totalMB $os.TotalVisibleMemorySize / 1MB $freeMB $os.FreePhysicalMemory / 1MB $usedMB $totalMB - $freeMB $percentUsed ($usedMB / $totalMB) * 100 # 获取内存占用高的进程 $processes Get-WmiObject Win32_Process -ComputerName $computer | Sort-Object -Property WS -Descending | Select-Object -First $TopProcessCount # 确定健康状态 if ($percentUsed -ge $CriticalThreshold) { $status Critical $color Red } elseif ($percentUsed -ge $WarningThreshold) { $status Warning $color Yellow } else { $status Healthy $color Green } # 准备进程信息 $processInfo $processes | ForEach-Object { [PSCustomObject]{ Name $_.Name PID $_.ProcessId MemoryMB [math]::Round($_.WS / 1MB, 2) MemoryPercent [math]::Round(($_.WS / $os.TotalVisibleMemorySize) * 100, 2) } } # 创建输出对象 [PSCustomObject]{ ComputerName $computer Status $status TotalMemoryGB [math]::Round($totalMB / 1024, 2) UsedMemoryGB [math]::Round($usedMB / 1024, 2) MemoryUsagePercent [math]::Round($percentUsed, 2) TopProcesses $processInfo Timestamp Get-Date -Format yyyy-MM-dd HH:mm:ss } | Write-Output } catch { Write-Warning 无法连接到服务器 $computer : $_ } } } # 使用示例 Get-ServerMemoryHealth -ComputerName SERVER01, SERVER02 -WarningThreshold 80 -CriticalThreshold 90

更多文章