powershell无法直接监控虚拟磁盘性能,需通过挂载卷、进程句柄路径及存储栈计数器间接实现:先定位虚拟磁盘对应卷(如e:),再按路径聚合进程i/o,结合physicaldisk与hyper-v虚拟设备计数器分析全链路吞吐。
powershell 本身不直接识别“虚拟磁盘”(如 vhdx、vmdk 或 hyper-v 虚拟 scsi 设备)为独立性能对象,但可通过关联物理磁盘、卷、进程与存储栈层级指标,间接监控其 i/o 行为。关键在于:不是查“虚拟磁盘名”,而是查“哪个进程在读写哪个卷/路径”,再结合该卷是否由虚拟磁盘承载。
一、确认虚拟磁盘挂载的卷和驱动器号
先明确你的虚拟磁盘是否已挂载为 Windows 卷(例如 D:、E:),并获取其底层物理位置:
- 运行 Get-VHD -Path "C:\VMs\disk.vhdx"(需 Hyper-V 模块)查看状态与关联磁盘号
- 执行 Get-Disk | Where-Object {$_.Location -like "*VHDX*"} | Get-Partition | Get-Volume 查找带 VHDX 标识的卷
- 更通用方式:Get-Volume | Where-Object {$_.FileSystemLabel -match "VM|VHDX|DataDisk"}(按标签筛选)
- 记下目标卷的 DriveLetter(如 E:)和 ObjectId(如 \Volume{a1b2c3d4-...}),后续用于关联 I/O 数据
二、按卷路径聚合进程级读写(推荐:精准定位虚拟磁盘使用者)
资源监视器和任务管理器无法按卷区分 I/O,但 PowerShell 可通过句柄路径反向统计——这是监控虚拟磁盘 I/O 最实用的方法:
- 使用 Get-Process | ForEach-Object { $p = $_; $_.Handles | Where-Object { $_.HandleType -eq 'File' } | ForEach-Object { try { $path = $_.Path; if ($path -and $path.StartsWith('E:\')) { [PSCustomObject]@{ ProcessName = $p.ProcessName; PID = $p.Id; Path = $path; Handle = $_.Handle } } } catch {} } }
- 配合 Get-Counter '\Process(*)\IO Read Bytes/sec','\Process(*)\IO Write Bytes/sec' 获取原始速率后,用 Get-Process -Id XXX | Select-Object Path 确认启动路径是否指向 VM 相关目录(如 C:\Program Files\Hyper-V\ 或 C:\VMs\)
- 若虚拟磁盘被映射为 NTFS 卷,所有对该卷路径(如 E:\data\)的读写,都会计入对应进程的 I/O 计数器中——你只需聚焦这些进程
三、监控底层存储栈:物理磁盘 + 虚拟控制器设备
对于 Hyper-V 等场景,虚拟机 I/O 最终经由物理磁盘和虚拟 SCSI 控制器转发。可查以下计数器:
- Get-Counter '\PhysicalDisk(*)\Disk Read Bytes/sec', '\PhysicalDisk(*)\Disk Write Bytes/sec' —— 看物理层总吞吐,判断是否饱和
- Get-Counter '\Hyper-V Virtual Storage Device(*)\Read Operations/sec', '\Hyper-V Virtual Storage Device(*)\Write Operations/sec' —— 若启用了 Hyper-V 性能计数器(需管理员权限且服务运行),可直击虚拟设备层
- 注意:该计数器实例名含 GUID 或 VM 名称,可用 Get-Counter -ListSet 'Hyper-V*' | Select-Object CounterSetName, Paths 列出可用路径
四、导出高 I/O 进程并标注是否涉及虚拟磁盘路径
以下命令一次性输出前 8 名写入进程,并标记其启动路径或句柄是否落在已知虚拟磁盘卷上(例如 E:\):
Get-Counter '\Process(*)\IO Write Bytes/sec' -MaxSamples 2 | ForEach-Object {
$_.CounterSamples | Where-Object { $_.CookedValue -gt 1MB } |
Sort-Object CookedValue -Descending |
Select-Object -First 8 -Property InstanceName,
@{Name='WriteBytesPerSec';Expression={$_.CookedValue}},
@{Name='ImagePath';Expression={ (Get-Process -Id $_.InstanceName -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Path -ErrorAction SilentlyContinue) }},
@{Name='InVirtualDiskVolume';Expression={
$path = $_.ImagePath;
if ($path -and ($path.StartsWith('E:\') -or $path.Contains('VMs') -or $path.Contains('VHDX'))) { '✓' } else { '' }
}}
}
替换 E:\ 为你实际的虚拟磁盘驱动器号;结果中带 ✓ 的进程极可能正在操作虚拟磁盘。











