I currently have this script which I am trying to get to display the % of processor load. Its returns results and seemingly reports correctly but it doesnt show the actual % in the output:
SCRIPT:
$Servers = Get-QADComputer -sizelimit 0 | where {$_.Name -like "*MYSERVER*"} | select Name | sort name
# Best practice: avoid magic numbers; readonly variable for
new-variable -name CPULIMIT -value 75 -option readonly
foreach($Server in $Servers){
$result = Get-WmiObject win32_processor -ComputerName $Server.Name
# TODO: add error handler here in case $server is unavailable
# Compare the wmi query result to the limit constant
if($result.LoadPercentage -le $CPULIMIT){
# Write a formatted string that contains the server name and current load
Write-Host $("Less than 75% Processor Load on {0} ({1}%)" -f $server.name, $result.LoadPercentage) -ForegroundColor "Green"
} else {
# A warning message would be usefull too
Write-Host $("More than 75% Processor Load on {0} ({1}%)" -f $server.name, $result.LoadPercentage) -ForegroundColor "Red"
}
}
OUTPUT:
Less than 75% CPU Load on MYSERVER1 (%)
Less than 75% CPU Load on MYSERVER2 (%)
Less than 75% CPU Load on MYSERVER3 (%)
Less than 75% CPU Load on MYSERVER4 (%)
As you can see there is now over all (%) displayed.
Any ideas would be greatly apprecaited.
Thanks
Jon Z adjustement of $result[0].LoadPercentage worked perfectly. Thank you.
Related
I want the CPU to be displayed as a percentage at the end of the code I wrote. Is there a way?
this is my code
Get-Process svchost | % $_.CPU
Hardly made it this far, only last episode left
Thanks #Santiago for pointing out the issue that it was the reading for the same svchost instance everytime, this is fixed now.
The code below borrows heavily from this thread: Powershell Get a specific process counter with id process
to get the correct reading.
This gets you the Path, the Id and %.
$procResult = Get-Process -Name svchost
$resultObjects = #();
foreach ($result in $procResult) {
$p = $((Get-Counter '\Process(*)\ID Process' -ErrorAction SilentlyContinue).CounterSamples | % { [regex]$a = "^.*\($([regex]::Escape($_.InstanceName))(.*)\).*$";[PSCustomObject]#{InstanceName=$_.InstanceName;PID=$_.CookedValue;InstanceId=$a.Matches($($_.Path)).groups[1].value}})
$target = $p | where { $_.PID -eq $result.Id }
$counterResult = Get-Counter -Counter "\Process($($target.InstanceName+$target.InstanceId))\% Processor Time" -ErrorAction SilentlyContinue
if ($null -eq $counterResult) {
continue;
}
$resultObjects += [PSCustomObject]#{
Path = $result.Path
Id = $result.Id
CPU = $counterResult.CounterSamples[0].CookedValue
}
}
$resultObjects | ft
You won't get the CPU usage in % with your code above. I really do not know why you insist on not changing the structure of your code as the structure of code is irrelevant as long as it is readable and get the job done.
I want a PowerShell script to get the total memory space of C drive and used memory space in GB, if the total space is less than 200 GB it should print disk space is less than 200.
gwmi win32_logicaldisk | Format-Table DeviceId, MediaType, #{n="Size";e={[math]::Round($_.Size/1GB,2)}},#{n="FreeSpace";e={[math]::Round($_.FreeSpace/1GB,2)}}
$task=gwmi win32_logicaldisk | Format-Table DeviceId, MediaType, #{n="Size";e={[math]::Round($_.Size/1GB,2)}},#{n="FreeSpace";e={[math]::Round($_.FreeSpace/1GB,2)}}
if($task.Size -lt 200)
{
Write-Host "Hard Disk Space is less than 200."
}
else
{
Write-Host "Hard Disk Space is greater than 200."
}
I am getting all drive space on the above code, I need only C drive information and if condition is not working properly,Some one help me through this. Thanks in advance
You can use the Get-Volume cmdlet -
if (((Get-Volume -DriveLetter C).Size)/1GB -lt 200)
{
Write-Host "Hard Disk Space is less than 200."
}
else
{
Write-Host "Hard Disk Space is greater than 200."
}
if you need to run this test on win7 - even with ps5.1 - you can't use the Get-Volume cmdlet. [sigh ...] so here is one that uses CMI/WMI for that.
what it does ...
sets a min free space threshold
uses the faster, non-deprecated CIM stuff to get the info on drive C:
only returns info if the C: drive meets the min freespace requirement
uses [string]::IsNullOrEmpty() to see if the result has any info in it
then uses an IF structure to decide what message to show
if space is too low, it uses the Write-Warning cmdlet for the nice orange text [grin]
here's the code ...
$MinFreeSpace_GB = 800
$CDriveMinFree = [string]::IsNullOrEmpty((Get-CimInstance -ClassName CIM_LogicalDisk |
Where-Object {
$_.DeviceID -eq 'C:' -and
$_.FreeSpace -lt $MinFreeSpace_GB * 1GB
}))
if ($CDriveMinFree)
{
'The C: drive has at least {0} GB free.' -f $MinFreeSpace_GB
}
else
{
Write-Warning ('Low free space on Drive C:!')
}
output on my 600 GB free C: drive with the test threshold set to 800 ...
WARNING: Low free space on Drive C:!
Have the following which works OK, but with an in issue in PowerShell:
$FileName = "E:\Work\ps\Inventory.htm"
$serverlist = "E:\Work\ps\Monitored_computers.txt"
foreach ($server in Get-Content $serverlist)
{
$servern=$server.split(",")[0]
$ip=$server.split(",")[1]
$cpu = gwmi Win32_PerfFormattedData_PerfProc_Process -Computer $servern -filter "Name <> '_Total' and Name <> 'Idle'" | Sort-Object PercentProcessorTime -Descending | where { $_.PercentProcessorTime -gt 0 }| select -First 1
if ($cpu.PercentProcessorTime -ge "92") {
write-host $servern ' ' $cpu.Name ' ' $cpu.PercentProcessorTime
}
}
I have seen some other code in PowerShell, that takes an Average but almost seems like an "average of an average" - which is meaningless. And, this is for overall CPU Usage
gwmi win32_processor | Measure-Object -property LoadPercentage -Average | Foreach {$_.Average}
Now, if we can take the same logic and apply for our process issue:
gwmi Win32_PerfFormattedData_PerfProc_Process | Sort-Object PercentProcessorTime -Descending | where { $_.PercentProcessorTime -gt 0 } | select -First 1 | Measure-Object -property PercentProcessorTime -Average | Foreach {$_.PercentProcessorTime}
What am trying to ask is: I do get the CPU Percentage, which seems to be a "point in time". How do locate the true CPU Percentage? This is why I am pointing out the average. I really want to get around the "point in time" part of this.
The point being, when we have seen on several occasions, a high CPU per process on a server, we login to the server and the high CPU has subsided. This is not to say, this has been each time, but we know that sometimes a CPU will spike and then quiet down.
Thanks for any insight!
First issue, you are stuck at a Point In Time because when you execute your script it captures a snapshot of what is happening right then and there. What you are looking for is historical data, so you can figure out the average CPU usage of processes over a set amount of time, and pinpoint the process that's bogging down your CPU. Do you have performance monitors in place to track CPU usage for individual processes? You may need to setup performance logging if you want to be able to get the numbers you're looking for after the fact.
Secondly, I think that you misunderstand how Measure-Object works. If you run Get-Help on the cmdlet and check the Output you'll see that it outputs a GenericMeasureInfo object. This object will have a property for the relevant stat that you are looking for, which in your case is the Average property. It is not an average of an average, the most common usage I see for it is to calculate something, like a Sum or Average, and then output the value of that property.
Let's try a simple example...
Find the average size of the files in a folder. First we use Get-ChildItem to get a collection of files, and pipe it to Measure-Object. We will specify the -Average argument to specify that we want the Average calculated, and -Property length, so that it knows what to average:
GCI C:\Temp\* -file | Measure-Object -Average -Property length
This outputs a GenericMeasureInfo object like this:
Count : 30
Average : 55453155
Sum :
Maximum :
Minimum :
Property : Length
That lets me know that it had 30 files piped to it, and it found the Average for the Length property. Now, sometime you want to calculate more than one thing, so you can use more than one argument, such as -Sum and -Maximum, and those values will be populated as well:
Count : 30
Average : 55453155
Sum : 1663594650
Maximum : 965376000
Minimum :
Property : Length
So it looks like my average file is ~55MB, but out of the 1.6GB in the whole folder I've got one file that's 965MB! That file is undoubtedly skewing my numbers. With that output I could find folders that have multiple files, but one file is taking up over half of the space for the folder, and find anomalies... such as the ISO that I have saved to my C:\temp folder for some reason. Looks like I need to do some file maintenance.
Thanks to #TheMadTechnician I have been able to sort this out. I had a wrong component with
$_.Average
where I had
$_.PercentProcessorTime
and that would never work. Here is the correct script:
$serverlist = "D:\Work\ps\Monitored_computers.txt"
foreach ($server in Get-Content $serverlist) {
$servern=$server.split(",")[0]
$ip=$server.split(",")[1]
$cpu = gwmi Win32_PerfFormattedData_PerfProc_Process -Computer $ip | `
Where-Object {$_.Name -like "*tomcat*"} | `
Measure-Object -property PercentProcessorTime -Average | `
Foreach {$_.Average}
if ($cpu -ge "20") {
write-host $servern $cpu ' has a tomcat process greater than 20'
}
}
I want to get the CPU usage % (not processor time) of a particular process using a powershell command.
Example: (Windows 8 Task Manager)
I want to get that 2.9% with a command.
Here is the correct answer which is support case then you have multiple processs with same name https://stackoverflow.com/a/34844682/483997
# To get the PID of the process (this will give you the first occurrance if multiple matches)
$proc_pid = (get-process "slack").Id[0]
# To match the CPU usage to for example Process Explorer you need to divide by the number of cores
$cpu_cores = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors
# This is to find the exact counter path, as you might have multiple processes with the same name
$proc_path = ((Get-Counter "\Process(*)\ID Process").CounterSamples | ? {$_.RawValue -eq $proc_pid}).Path
# We now get the CPU percentage
$prod_percentage_cpu = [Math]::Round(((Get-Counter ($proc_path -replace "\\id process$","\% Processor Time")).CounterSamples.CookedValue) / $cpu_cores)
Get-Process -Name system | select CPU
Get the cpu time at 2 instance as (cpu2-cpu1)/(t2-t1)*100. You will get CPU value in %.
Get-Process -Name system | select CPU # Get the cpu time at 2 instance as (cpu2-cpu1)/(t2-t1)*100. You will get CPU value in %.
$processName = 'OUTLOOK'
$sleep_time = 1 # value in seconds
while (1) {
$CPU_t1 = Get-Process -Name $processName | Select CPU
$CPU_t1_sec = $($CPU_t1.CPU)
#Write-Host "CPU_t1: $($CPU_t1.CPU)"
$date1 = (Get-Date)
sleep -Seconds $sleep_time
$CPU_t2=Get-Process -Name $processName | Select CPU
#Write-Host "CPU_t2: $($CPU_t2.CPU)"
$CPU_t2_sec = $($CPU_t2.CPU)
$date2 = (Get-Date)
$date_diff = $date2 - $date1
$diff_time = $date_diff.seconds
#Write-Host "TimeDiff: $diff_time"
#compute them to get the percentage
$CPU_Utilization = ($CPU_t2_sec - $CPU_t1_sec)/$diff_time
$CPU_Utilization_per = $CPU_Utilization * 100
#Sleep $sleep_time
Clear-Host Write-Host "CPU_Utilization_Per: $CPU_Utilization_per"
#Write-Host "====================="
}
Get-Process -Name PowerShell | Select CPU
Is this what you're looking for?
Or something more monitoring based?
param
(
[String]
[Parameter(Mandatory)]
$Title
)
do
{
$process = Get-Process -Name $Title
$process
Start-Sleep -Seconds 1
} while ($process)
I want to get specific counters for processes that I have process id's for. However I can't think of a way to use where-object to match the process for the counter.
Like
Where Gc '\process(*)\id process -eq 456 gc '\process($name)\working set'
So use the process id to retrieve the name and get the working set (or something to that effect).
It seems a bit convoluted to get the correct performance counter path for a process with multiple instances of the same process name:
$proc_id=6580
$proc_path=((Get-Counter "\Process(*)\ID Process").CounterSamples | ? {$_.RawValue -eq $proc_id}).Path
Get-Counter ($proc_path -replace "\\id process$","\% Processor Time")
Timestamp CounterSamples
--------- --------------
11/20/2014 5:39:15 PM \\myhost\process(conhost#2)\% processor time :
0
You can get counters for a process name so first get the process name by using its Id and then embed the process name in the counter. For example:
$id = # your process id
$proc = (Get-Process -Id $id).Name
Get-Counter -Counter "\Process($proc)\% Processor Time"
If you want a solution that also include process with multiple instance IDs you can use :
$p = $((Get-Counter '\Process(*)\ID Process' -ErrorAction SilentlyContinue).CounterSamples | % {[regex]$a = "^.*\($([regex]::Escape($_.InstanceName))(.*)\).*$";[PSCustomObject]#{InstanceName=$_.InstanceName;PID=$_.CookedValue;InstanceId=$a.Matches($($_.Path)).groups[1].value}})
# In french, use '\processus(*)\id de processus' for the counter name
$id = # your process id
$p1 = $p | where {$_.PID -eq $id}
Get-Counter -Counter "\Process($($p1.InstanceName+$p1.InstanceId))\% Processor Time"
# In french, use "\Processus($($p1.InstanceName+$p1.InstanceId))\% temps processeur" for the counter name
Or if you avoid to use Get-Counter and wait the sample interval, try use WMI:
$id = YourProcessIdHere
(gwmi -class Win32_PerfRawData_PerfProc_Process -Namespace "root\CIMV2" | ? {$_.IdProcess -eq $id}).Name;
It is possible to obtain some performance information with the Get-Process commandlet directly and avoid the need to resolve an instance ID.
For the case of the memory working set, just filter the output for the process id you want using where-object, then select the parameters you're interested in:
get-process | where-object{ $_.id -eq 456 } | select name,workingset