问题
I have developed PowerShell script which monitors server performance like average CPU utilization, Memory and Cdrive and if any of the resource crosses the threshold it will trigger mail. My script is running fine but I want to monitor it for 30 minutes and if in 30 minutes it cross threshold only then it will trigger the mail.
<#
.SYNOPSIS
Script for the detailed server health report
.DESCRIPTION
The script accepts parameter from CSV file by which we can get details and
all information related to health status of the server.The script generates all the
information in a CSv file.
#>
[CmdletBinding(SupportsShouldProcess=$True)]
param(
[Parameter(Position=0,mandatory=$true)]
[string]$Servercsv
)
begin{
Write-Host "Running"
}
process{
# Path for the CSV file that contains all the Print Server information.
$ServerDetails=import-csv $Servercsv
$result=@()
$Outputreport = $null
foreach($server in $ServerDetails){
try{
#sysinfo variable contains complete systeminfo like manufacturer name, physical memory,servername
$cpu=Get-WMIObject -ComputerName $server.servers win32_processor| select __Server, @{name="CPUUtilization" ;expression ={“{0:N2}” -f (get-counter -Counter "\Processor(_Total)\% Processor Time" -SampleInterval 1 -MaxSamples 6 |
select -ExpandProperty countersamples | select -ExpandProperty cookedvalue | Measure-Object -Average).average}}
$disks =Get-WmiObject -Class win32_Volume -ComputerName $server.servers -Filter "DriveLetter = 'C:'" |
Select-object @{Name = "PercentFree"; Expression = {“{0:N2}” -f (($_.FreeSpace / $_.Capacity)*100) } }
$os=Get-WmiObject -Class win32_operatingsystem -computername $server.servers |
Select-Object @{Name = "MemoryUsage"; Expression = {“{0:N2}” -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize) }}
$result += [PSCustomObject] @{
ServerName ="$($server.servers)"
CPUUtilization = $cpu.CPUUtilization.ToString()
CDrive = $disks.PercentFree
MemLoad = $OS.MemoryUsage
}
}
catch{
"error communicating with $($server.servers), skipping to next"
}
}
$Outputreport = "<HTML><TITLE> Utilization of Server Resources</TITLE>
<BODY background-color:peachpuff>
<font color =""#99000"" face=""arial"">
<H3> Utilization of Server Resources</H3></font>
<Table border=2 cellpadding=1 cellspacing=5>
<TR bgcolor=gray align=center>
<TD><B>Server Name</B></TD>
<TD><B>CPUUtilization</B></TD>
<TD><B>Memory Utilization</B></TD>
<TD><B>CDrive</B></TD></TR>"
Foreach($Entry in $Result){
if(([decimal]$Entry.CPUUtilization -ge 25) -or ([decimal]$Entry.MemLoad -ge 50) -or (([decimal]$Entry.CDrive) -le 60) )
{
$Outputreport += "<TR>"
$Outputreport += "<TD><B>$($Entry.Servername)</B></TD>"
if([decimal]$Entry.CPUUtilization -ge 25)
{
$Outputreport += "<TD align=center style=color:red;>$($Entry.CPUUtilization+'%')</TD>"
}
else {
$Outputreport += "<TD align=center style=color:White;>$($Entry.CPUUtilization+'%')</TD>"
}
if([decimal]$Entry.MemLoad -ge 50)
{
$Outputreport += "<TD align=center style=color:red;>$($Entry.MemLoad+'%')</TD>"
}
else{
$Outputreport += "<TD align=center style=color:White;>$($Entry.MemLoad+'%')</TD>"
}
if(([decimal]$Entry.CDrive) -le 60)
{
$Outputreport += "<TD align=center style=color:red;>$($Entry.Cdrive+'%')</TD>"
}
else{ $Outputreport += "<TD align=center style=color:White;>$($Entry.Cdrive+'%')</TD>"}
#$Outputreport += "<TD>$($Entry.Servername)</TD>"
#$Outputreport += "<TD>$($Entry.Servername)</TD>"
$Outputreport+="</TR>"
}
}
$Outputreport += "</Table><p>Regards,<br>Rujhaan Bhatia</p></BODY></HTML>"
$out=$Outputreport | ConvertTo-Html -Head $Outputreport
#Send an email about the Load
# $smtp is the outgoing mail server
$smtp= "smtphost.redmond.corp.microsoft.com"
try{
send-mailmessage -SmtpServer $smtp -from v-rubhat@microsoft.com -to v-rubhat@microsoft.com,v-ketr@microsoft.com -subject "Retail Servers Health Report" -BodyAsHtml "$out"
}
catch [exception]
{
write-host ("Cannot send mail, since argument is null or empty")
}
}
Please do suggest me if any changes are required in any of the command as well.
回答1:
This should give you an idea on how to run jobs in the background and check for 30 minutes. If at any time the cpu, mem or disk is greater than threhold, send email.
function SendEmail {
param($server, $cpu, $mem, $disk)
#Code goes here to send email
}
$cpuThreshold = 99
$memThreshold = 99
$diskThreshold = 100
$jobHash = @{}
$serverHash = @{}
$serverList = @("localhost")
foreach($server in $serverList) {
$cpu = Start-Job -ComputerName $server -ScriptBlock { Get-Counter "\processor(_Total)\% Processor Time" -Continuous }
$mem = Start-Job -ComputerName $server -ScriptBlock { Get-Counter -Counter "\Processor(_Total)\% Processor Time" -Continuous }
$disk = Start-Job -ComputerName $server -ScriptBlock { Get-Counter -Counter "\LogicalDisk(C:)\% Free Space" -Continuous }
$serverHash.Add("cpu", $cpu)
$serverHash.Add("mem", $mem)
$serverHash.Add("disk", $disk)
$jobHash.Add($server, $serverHash)
}
Start-Sleep 10
$totalLoops = 0
while ($totalLoops -le 360) {
foreach($server in $jobHash.Keys) {
$cpu = (Receive-Job $jobHash[$server].cpu | % { (($_.readings.split(':'))[1]).Replace("`n","") } | measure -Maximum).Maximum
$mem = (Receive-Job $jobHash[$server].mem | % { (($_.readings.split(':'))[1]).Replace("`n","") } | measure -Maximum).Maximum
$disk = (Receive-Job $jobHash[$server].disk | % { (($_.readings.split(':'))[2]).Replace("`n","") } | measure -Maximum).Maximum
if ($Cpu -gt $cpuThreshold -or $mem -gt $memThreshold -or $disk -gt $diskThreshold) {
Send-Email $server $cpu $mem $disk
}
Write-Output "CPU: $($cpu), Mem: $($mem), disk util: $($disk)"
}
Start-Sleep 1
$totalLoops ++
}
Get-Job | Remove-Job
Hopefully this answers the question on how to create jobs in the background to check for status.
I would, however, check the max number of jobs you can have at any given time.
Documentation on Get-Counter
来源:https://stackoverflow.com/questions/60049690/need-to-monitor-server-resources-utilization-for-30-minutes-and-send-mail-in-pow