#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-WmiObject –class 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