Список процессов по проценту использования ЦП в powershell

#powershell

#powershell

Вопрос:

Как можно перечислить процессы, использующие процессор> 1%, передавая выходные данные из Get-Process в Where-Object ?

Полный новичок в powershell все, что я могу придумать, это что-то вроде этого

 Get-Process | Where-Object { CPU_Usage -gt 1% }
  

Комментарии:

1. Привет, вы пробовали запускать свой код (в консоли PowerShell или ISE)?

2. да, у меня есть, я получаю CommandNotFoundException

Ответ №1:

Если вам нужен процент использования ЦП, вы можете использовать Get-Counter для получения счетчика производительности, и Get-Counter можно запускать для всех процессов. Итак, чтобы перечислить процессы, которые используют больше, чем, скажем, 5% использования ЦП:

 (Get-Counter 'Process(*)% Processor Time').CounterSamples | Where-Object {$_.CookedValue -gt 5}
  

Здесь будут перечислены процессы, которые использовали> 5% ЦП в момент, когда была взята выборка. Надеюсь, это поможет!

Комментарии:

1. это должен быть ответ, а не мой. 1 в любом случае 🙂

2. Это хорошее рабочее решение, но оно не будет работать, если у вас есть несколько процессов с одинаковыми именами.

3. Обратите внимание, что если у вас несколько процессоров, значение CookedValue может превышать 100% для любого отдельного процесса, а также для _total .

4. Довольно раздражает, что в результате нет идентификатора процесса.

5. @RossPresser Это так. Однако Get-Counter может принимать несколько счетчиков, поэтому, если также используется счетчик ‘ Process (*) ID Process’, образец будет содержать PID. В результирующих образцах также будет указан экземпляр, заполненный по пути, например ‘Process(someinstance) countername’, где все значения могут быть связаны через экземпляр с небольшим извлечением.

Ответ №2:

Здесь следует отметить несколько моментов:

  • во-первых, вы должны использовать $_ переменную для ссылки на объект, который в данный момент поступает из канала.
  • во-вторых, Powershell не использует % для выражения процента — вместо % этого представляет оператор модуля. Итак, когда подразделение хочет получить процент, вы должны преобразовать свое число самостоятельно, просто умножив его на 0.01 .

  • в-третьих, Get-Process командлет не имеет поля CPU_Usage ; сводку о его выходных данных можно найти здесь. О поле CPU говорится: «Количество процессорного времени, которое процесс использовал на всех процессорах, в секундах». Так что четко представляйте, чего вы можете ожидать от этих цифр.

Обобщение команды может быть записано в виде

 Get-Process | Where-Object { $_.CPU -gt 100 }
  

Это дает вам процессы, которые использовали более 100 секунд процессорного времени.

Если вам нужно что-то вроде относительного утверждения, вам сначала нужно суммировать все использованные времена, а затем разделить фактическое время на общее время. Вы можете получить общее время процессора, например, с помощью

 Get-Process | Select-Object -expand CPU | Measure-Object -Sum | Select-Object -expand Sum
  

Попробуйте сложить его вместе с предыдущей командой.

Комментарии:

1. Есть ли какой-либо способ, с помощью которого мы можем получить процент ЦП, используемый процессом. Это должно быть значение, которое диспетчер задач показывает в столбце CPU%.

2. Принятый ответ приводит к некоторой ошибке. Ваш ответ лучше! 😉

Ответ №3:

Дальнейшее улучшение предыдущих ответов путем добавления динамического определения количества логических ядер, чтобы процентное соотношение можно было скорректировать до того, что мы, простые смертные, ожидаем увидеть, где 100% означает всю пропускную способность процессора машины, и нет значения больше 100%. Включает фильтр, установленный на 10%, который можно настроить соответствующим образом. Предполагается, что пользователи будут заинтересованы в поиске процессов с высокой загрузкой процессора и не захотят перечислять многочисленные простаивающие процессы машины.

 $NumberOfLogicalProcessors=(Get-WmiObject -class Win32_processor | Measure-Object -Sum NumberOfLogicalProcessors).Sum
(Get-Counter 'Process(*)% Processor Time').Countersamples | Where cookedvalue -gt ($NumberOfLogicalProcessors*10) | Sort cookedvalue -Desc | ft -a instancename, @{Name='CPU %';Expr={[Math]::Round($_.CookedValue / $NumberOfLogicalProcessors)}}
  

Пример вывода:

 InstanceName CPU %
------------ -----
_total         100
idle           100
  

Ответ №4:

Я искал решение для получения загрузки ЦП, памяти по процессу. Все решения, которые я пробовал, где я мог бы получить процессор, но эти цифры не совпадали с taskmanager. Поэтому я написал свой собственный. Ниже приведено точное использование ЦП каждым процессом. Я тестировал это на ноутбуке I7.

 $Cores = (Get-WmiObject -class win32_processor -Property numberOfCores).numberOfCores;
$LogicalProcessors = (Get-WmiObjectclass Win32_processor -Property NumberOfLogicalProcessors).NumberOfLogicalProcessors;
$TotalMemory = (get-ciminstance -class "cim_physicalmemory" | % {$_.Capacity})

 

$DATA=get-process -IncludeUserName | select @{Name="Time"; Expression={(get-date(get-date).ToUniversalTime() -uformat "%s")}},`
  ID,  StartTime,  Handles,WorkingSet, PeakPagedMemorySize,  PrivateMemorySize, VirtualMemorySize,`
   @{Name="Total_RAM"; Expression={ ($TotalMemory )}},`
  CPU,
   @{Name='CPU_Usage'; Expression = { $TotalSec = (New-TimeSpan -Start $_.StartTime).TotalSeconds
     [Math]::Round( ($_.CPU * 100 / $TotalSec) /$LogicalProcessors, 2) }},`
   @{Name="Cores"; Expression={ ($Cores )}},`
   @{Name="Logical_Cores"; Expression={ ($LogicalProcessors )}},`
 
 UserName, ProcessName, Path |  ConvertTo-Csv 
  

Или как [pscustomobject] :

 $cpu   = Get-WmiObject –class Win32_processor -Property NumberOfCores, NumberOfLogicalProcessors
$mem   = (Get-CimInstance -class cim_physicalmemory | measure capacity -sum).sum
$epoch = get-date(get-date).ToUniversalTime() -uformat "%s"

get-process -IncludeUserName | 
% { 
  if ($_.starttime -gt 0) {
    $ts       = (New-TimeSpan -Start $_.StartTime -ea si).TotalSeconds
    $cpuusage = [Math]::Round( $_.CPU * 100 / $ts / $cpu.numberoflogicalprocessors, 2)
  } else {
    $cpuusage = 0
  }

  [pscustomobject] @{
    "Time"                = $epoch
    "Total_RAM"           = $mem
    "CPU_Usage"           = $cpuusage
    "Cores"               = $cpu.numberofcores
    "Logical Cores"       = $cpu.numberoflogicalprocessors
    "UserName"            = $_.username
    "ProcessName"         = $_.processname
    "Path"                = $_.path
    "CPU"                 = $_.CPU
    "ID"                  = $_.ID
    "StartTime"           = $_.StartTime
    "Handles"             = $_.Handles
    "WorkingSet"          = $_.WorkingSet
    "PeakPagedMemorySize" = $_.PeakPagedMemorySize
    "PrivateMemorySize"   = $_.PrivateMemorySize
    "VirtualMemorySize"   = $_.VirtualMemorySize
  }
}
  

Ответ №5:

В дополнение к Get-Counter , вы также можете использовать Get-WmiObect для составления списка и фильтрации процессов.

 powershell "gwmi Win32_PerfFormattedData_PerfProc_Process -filter 'PercentProcessorTime > 1' | Sort PercentProcessorTime -desc | ft Name, PercentProcessorTime"
  

В качестве альтернативы, для Get-Counter , вот пример, показывающий преобразование числового формата, чтобы избавиться от раздражающих десятичных знаков в CookedValue .
В дополнение к фильтрации этот пример также иллюстрирует сортировку, ограничение столбцов и форматирование вывода:

 powershell "(Get-Counter 'Process(*)% Processor Time').Countersamples | Where cookedvalue -gt 3 | Sort cookedvalue -Desc | ft -a instancename, @{Name='CPU %';Expr={[Math]::Round($_.CookedValue)}}"
  

Get-Process это неправильный командлет, поскольку он не обеспечивает мгновенную загрузку ЦП.

Вы также можете получить общую нагрузку для всех процессоров:

 powershell "gwmi win32_processor | Measure-Object LoadPercentage -Average | ft -h Average"
  

Или,

 typeperf -sc 4 "Processor(_Total)% Processor Time"
  

Ответ №6:

Я хотел бы добавить свою версию кода, чтобы помочь любому, у кого возникли проблемы с теми же проблемами. Мне нужен был тот, который давал мне процессор и память, и это мое мнение по этому вопросу. Он может экспортироваться с течением времени, если вы настроите запланированную задачу в Windows, и он добавляется к выходному файлу CSV, и вы можете получить несколько процессов.

     $Cores = (Get-WmiObject -class win32_processor -Property numberOfCores).numberOfCores;
    $LogicalProcessors = (Get-WmiObject –class Win32_processor -Property NumberOfLogicalProcessors).NumberOfLogicalProcessors;
    $TotalMemory = (get-ciminstance -class "cim_physicalmemory" | % {$_.Capacity})
    #EDIT the PATH for the CSV output to be located
    $PATH = "C:temp"
    #You can add more processes here as variables or just CommaSeperate them like below
    $Process1 = 'explorer'
    $Process2 = 'chrome'

    Get-Process -Name $Process1,$Process2 | select @{N="TimeStamp";E={Get-Date -Format 'dd/MM/yyyy HH:mm:ss.fff'}},
      ID,  
      name,
      Handles,
      PeakPagedMemorySize,
      PrivateMemorySize,
      VirtualMemorySize,
      @{Name="Memory_MB"; Expression = {[Math]::Round(($_.workingSet / 1mb),2)}},
      @{Name='CPU_Usage'; Expression = { $TotalSec = (New-TimeSpan -Start $_.StartTime).TotalSeconds [Math]::Round( ($_.CPU * 100 / $TotalSec) /$LogicalProcessors, 2) }},
      @{Name="Cores"; Expression={ ($Cores )}},
      @{Name="Logical_Cores"; Expression={ ($LogicalProcessors )}},
      Path | Export-Csv -Path "$PATHCPU_MEMORY_$env:COMPUTERNAME.csv" -NoTypeInformation -Append
  

Я знаю, что это выше вопроса OP и идет немного дальше, но я надеюсь, что это поможет!

Ответ №7:

Для параллельного вызова нескольких серверов и возврата process, cpu usage, servername и corecount хорошо работает следующее.

Потребуется 10 выборок за 10 секунд и среднее значение. Вы можете изменить это с помощью параметра MaxSamples .

Я считаю, что это менее элегантная версия того, что делает Эмра Саглама, я просто пугаюсь и смущаюсь всеми его каналами 🙂

 $allServers = "server1", "PC001", "server2"

#Change value of MaxSamples to the number of samples to take. Samples are taken in 1sec intervals
$CPUUsage = Invoke-Command -ComputerName $allServers -ScriptBlock {
    $counters = (Get-Counter "Process(*)% Processor Time" -MaxSamples 10).CounterSamples | Sort-Object -Property CookedValue -Descending
    [int]$coreCount = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors
    $counters | ForEach-Object {
        Add-Member -MemberType NoteProperty -Name "CPU_PCT" -Value ([math]::Round($_.CookedValue / $coreCount))[0] -InputObject $_
        Add-Member -MemberType NoteProperty -Name "Host" -Value ($_.Path -replace "^\\|\process.*$","") -InputObject $_
        Add-Member -MemberType NoteProperty -Name "CoreCount" -Value $coreCount -InputObject $_
    }
    $counters | Select-Object InstanceName,CPU_PCT,Host,Path,CoreCount
}

#Unhash to see all samples:
#$CPUUsage | Sort-Object -Property Host,CPU_PCT -Descending | Select-Object -Property Host,InstanceName,CPU_PCT,Path,CoreCount | Out-GridView -Title "CPU Usage"

#Group samples, add wanted values and take average. Add values to new object
$CPUUsageGrouped = $CPUUsage | Group-Object -Property InstanceName,Host
$CPUUsageGrouped | ForEach-Object {
    Add-Member -MemberType NoteProperty -Name "CPUavg" -Value (($_.Group.CPU_PCT | Measure-Object -Sum).Sum / $_.Count) -InputObject $_
    Add-Member -MemberType NoteProperty -Name "CPUmin" -Value ($_.Group.CPU_PCT | Sort-Object)[0] -InputObject $_
    Add-Member -MemberType NoteProperty -Name "CPUmax" -Value ($_.Group.CPU_PCT | Sort-Object)[$_.Count -1] -InputObject $_
    Add-Member -MemberType NoteProperty -Name "Host" -Value $_.Group.Host[0] -InputObject $_
    Add-Member -MemberType NoteProperty -Name "CoreCount" -Value $_.Group.CoreCount[0] -InputObject $_
    Add-Member -MemberType NoteProperty -Name "InstanceName" -Value $_.Group.InstanceName[0] -InputObject $_
}

#Sort the grid view with the build in search functions
$CPUUsageGrouped | Sort-Object -Property Host,CPUavg -Descending | Select-Object -Property Host,InstanceName,CPUavg,CoreCount,CPUmin,CPUmax | Out-GridView -Title "CPU Usage"
  

Ответ №8:

Как насчет этого для одного процесса?

 $sleepseconds = 1
$numcores = 4
$id = 5244

while($true) {
  $cpu1 = (get-process -Id $id).cpu
  sleep $sleepseconds
  $cpu2 = (get-process -Id $id).cpu
  [int](($cpu2 - $cpu1)/($numcores*$sleepseconds) * 100)
}
  

Ответ №9:

 $Result = Invoke-Command -ComputerName $ServerName -ScriptBlock {
    Get-Counter "Process(*)% Processor Time" -ErrorAction SilentlyContinue `
    | Select-Object -ExpandProperty CounterSamples `
    | Where-Object {$_.Status -eq 0 -and $_.instancename -notin "_total", "idle", "" -and $_.CookedValue/$env:NUMBER_OF_PROCESSORS -gt 0} `
    | Sort-Object CookedValue -Descending `
        | Select-Object @{N="ServerName";E={$env:COMPUTERNAME}},
        @{N="ProcessName";E={
            $friendlyName = $_.InstanceName
            try {
                $procId = [System.Diagnostics.Process]::GetProcessesByName($_.InstanceName)[0].Id
                $proc = Get-WmiObject -Query "SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId =$procId"
                $procPath = ($proc | where { $_.ExecutablePath } | select -First 1).ExecutablePath
                $friendlyName = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription
            } catch { }
            $friendlyName
        }},
        @{N="CPU_Percent";E={[System.Math]::Round(($_.CookedValue/$env:NUMBER_OF_PROCESSORS), 2)}},
        @{N="TimeStamp";E={Get-Date -Format 'dd/MM/yyyy HH:mm:ss.fff'}} -First 10 `
 $Result
} 

# If you want to export result to your SQL Server table you can use DbaTools Powershell Modules.
$Result | Select -Property ServerName, ProcessName, CPU_Percent, TimeStamp | ConvertTo-DbaDataTable | Write-DbaDbTableData -SqlInstance $OutInstance -Database $OutDB -Schema dbo -Table WindowsTopCPUProcesses
  

Комментарии:

1. когда я устанавливаю $ServerName в win32_computersystem.name в экземпляре AWS EC2, который я получаю, доступ запрещен, исключение PSRemotingTransportException