You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Get-Counter无法获取有效进程I/O数据的技术咨询

PowerShell 获取进程I/O详情常见问题与解决思路

先贴一下你提到的基础脚本,方便上下文参考:

$gc = get-counter -ComputerName $($service.ServerName) "\Process($Tservicename)\IO Other Bytes/sec" -ErrorAction SilentlyContinue
$OtherBytes=$gc.CounterSamples|Select cookedvalue

其中$serviceName与ServerName会循环遍历。

下面逐个解决你遇到的问题:

1. 无法获取所有服务的IO Other Bytes详情

虽然你已经用管理员权限运行,但还是有几个常见原因导致拿不到数据:

  • 进程实例名称不匹配:很多系统进程(比如svchost.exe)的性能计数器实例会带#数字后缀(比如svchost#1),直接用原始服务名/进程名可能匹配不到。建议先枚举目标机器上所有可用的Process类计数器实例,确认目标进程的正确名称:
    Get-Counter -ComputerName $($service.ServerName) "\Process(*)\IO Other Bytes/sec" | Select-Object -ExpandProperty CounterSamples | Select-Object InstanceName, CookedValue
    
  • 错误被静默掩盖:你加了-ErrorAction SilentlyContinue,会把计数器不存在、进程已退出等错误隐藏。可以暂时去掉这个参数,看看具体报错信息,针对性排查。
  • 进程未启用对应计数器:极少数情况下,某些进程可能没有注册I/O类的性能计数器,这种情况可以尝试重启目标进程,或者用管理员权限执行lodctr /r重置系统性能计数器。

2. 同名多进程(如chrome.exe)的处理

你的当前脚本如果直接指定进程名,当存在多个同名进程时,不会返回累计值,反而会因为匹配到多个实例而报错(如果没加静默错误处理的话)。要获取每个进程的详情,需要这样做:

  1. 先获取该进程名对应的所有实例:
    $allProcessCounters = Get-Counter -ComputerName $($service.ServerName) "\Process(*)\IO Other Bytes/sec" | Select-Object -ExpandProperty CounterSamples
    $targetInstances = $allProcessCounters | Where-Object {$_.InstanceName -match "^$Tservicename(#\d+)?$"}
    
    这里用正则匹配,既能匹配纯进程名,也能匹配带#数字后缀的实例。
  2. 遍历每个实例单独取值:
    foreach ($instance in $targetInstances) {
        $result = [PSCustomObject]@{
            ServerName = $service.ServerName
            ProcessInstance = $instance.InstanceName
            IOOtherBytesPerSec = $instance.CookedValue
        }
        # 可以把$result存入数组或者输出到文件
        $result
    }
    

3. IO读取/写入字节多数返回0的问题

你自己研究出的结论完全正确,这里再补充下细节:

  • 采样间隔导致的0值:Get-Counter默认的CookedValue是采样间隔内的I/O增量,如果进程在默认1秒的采样窗口里没有I/O操作,就会返回0。可以通过-SampleInterval设置更长的采样时间,同时用-MaxSamples采集多次数据计算平均值:
    # 采样间隔5秒,采集2次数据,计算间隔内的平均I/O
    $gc = Get-Counter -ComputerName $($service.ServerName) "\Process($Tservicename)\IO Read Bytes/sec" -SampleInterval 5 -MaxSamples 2
    $avgValue = ($gc.CounterSamples.CookedValue | Measure-Object -Average).Average
    
  • 累计值获取:如果需要服务器启动以来的累计I/O总量,直接取RawValue即可,这个值是系统启动后到当前的累计值,不受采样间隔影响:
    $OtherBytes = $gc.CounterSamples | Select-Object InstanceName, RawValue
    

内容的提问来源于stack exchange,提问作者SQLDoctor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 08:37:37