Powershell‎ > ‎Stuff‎ > ‎

Monitor Disk Freespace


Monitor Disk in all Servers


#Get a list of all servers then go through that list and get all local drives and email a report with 
#a summary of the most critical drives and errors and attach the full list

IF (Get-PSSnapin | where {$_.name -eq "quest.activeroles.admanagement"}) 
    {write-host "Quest Active Roles snapin already loaded"}
Else
    {add-PSSnapin  quest.activeroles.admanagement}

$CriticalFreeSpaceGB = .5
$WarningFreeSpacePercent = 5
$smtpServer = "mail.blah.com"
#$To = "Kevin Curran <kcurran@blah.com>"
$From = "AD Reporting <ADReporting@blah.com>"

$OutputFile = "c:\Temp\ServerDriveUsage.csv"
$Counter = $null
Function check-even ($num) {[bool]!($num%2)}

$WindowsServers = Get-QADComputer -SizeLimit 0 -OSName "*windows*server*" | select Name, OperatingSystem
#Testing
#$WindowsServers = Get-QADComputer -SizeLimit 0 -OSName "*windows*server*" | select Name, OperatingSystem -First 30
#$WindowsServers | Group-Object -Property operatingsystem | select count, name

$DriveReport =@()
foreach ($Server in $WindowsServers)
{
    $DNS = $null
    $pingable = $null
    $WMIError = $null
    $ErrorString = $null
    $ErrorMessage = ""
    $Counter ++
    Write-Host $Counter $Server.Name
    
    $DNS = [System.Net.Dns]::GetHostByName($Server.Name)
    If ($DNS) 
    {
        $pingable=$(Test-Connection -Quiet -count 2 -ComputerName $Server.Name)
        If ($pingable)
        {
            #Add a where filter to exclude drives in the non active cluster node
            $DriveReport += Get-WmiObject -ErrorVariable WMIError -ErrorAction SilentlyContinue Win32_LogicalDisk -Filter "DriveType='3'" -ComputerName $Server.Name | 
                Where {$_.Size -ne $null} |
                select @{Name='Machine';Expression={$Server.Name}}, 
                @{Name='Drive';Expression={$_.DeviceID}},
                @{Name='SizeGB';Expression={[Math]::Round($($_.Size / 1GB),1)}},
                @{Name='FreespaceGB';Expression={[Math]::Round($($_.FreeSpace / 1GB ),1)}},
                @{Name='PercentFree';Expression={[Math]::Round($($_.FreeSpace /$_.Size * 100),1)}},
                @{Name='ErrorMessage';Expression={""}}
            $ErrorMessage = If ($WMIError)
            {
                $ErrorString = "$WMIError"
                If($ErrorString -like '*Access is denied*'){"WMI Error - Access is denied"}
                ElseIf($ErrorString -like '*OutOfMemoryException*'){"WMI Error - OutOfMemoryException"}
                ElseIf($ErrorString -like '*Server execution failed*'){"WMI Error - Server execution failed"}
                ElseIf($ErrorString -like '*RPC server is unavailable*'){"WMI Error - RPC server is unavailable"}
                ElseIf($ErrorString -like '*Not Found*'){"WMI Error - Not Found"}
                Else 
                {
                    #return the errorstring to ErrorMessage variable and write the new WMI error to a log file
                    $ErrorString
                    #$WMIError | Out-File .\$($Server.Name)_error.txt
                }
            }
        }
        Else
        {
            #Write Error unable to ping server
            $ErrorMessage = "Error unable to ping Server $($Server.Name)"
        }
    }
    Else
    {
        #Write Error no DNS entry found
        $ErrorMessage = "Error unable to find DNS entry for $($Server.Name)"
    }
    
    IF ($ErrorMessage)
    {
        $DriveReport +=  $Server.Name | select @{Name='Machine';Expression={$Server.Name}},
            @{Name='Drive';Expression={""}},
            @{Name='SizeGB';Expression={""}},
            @{Name='FreespaceGB';Expression={""}},
            @{Name='PercentFree';Expression={""}},
            @{Name='ErrorMessage';Expression={$ErrorMessage}}
    }
}

$DriveReport | Export-Csv -NoTypeInformation -Path $OutputFile

$CriticalDrives = $DriveReport | where {$_.ErrorMessage -eq "" -and $_.FreespaceGB -le $CriticalFreeSpaceGB} | Sort-Object -Property FreespaceGB
$WarningDrives = $DriveReport | where {$_.ErrorMessage -eq "" -and $_.FreespaceGB -gt $CriticalFreeSpaceGB -and $_.PercentFree -le $WarningFreeSpacePercent} | Sort-Object -Property PercentFree
$ErrorDrives = $DriveReport | where {$_.ErrorMessage -ne ""}

$Message = $CriticalDrives | ConvertTo-Html -Fragment -Property Machine, Drive, SizeGB, FreespaceGB, PercentFree -PreContent "<b>Critical Drives (less than $CriticalFreeSpaceGB GB freespace) </b>" | ForEach-Object {$_}
$Message += $WarningDrives | ConvertTo-Html -Fragment -Property Machine, Drive, SizeGB, FreespaceGB, PercentFree -PreContent "<br><b>Warning Drives (less than $WarningFreeSpacePercent Percent freespace)</b>" | ForEach-Object {$_}
$Message += $ErrorDrives | ConvertTo-Html -Fragment -Property Machine, ErrorMessage -PreContent "<br><b>Errors</b> <br>If these machines do not exist please decommission them and remove from Active Directory" | ForEach-Object {$_}

$Counter = $null
#Modify HTML alternate row color
$ModifiedHTML=ForEach ($line in $Message)
{
    $counter++
    if (check-even $counter)
     {$line.replace('<tr><td>','<tr class="d0"><td>')}
    Else
     {$line.replace('<tr><td>','<tr class="d1"><td>')}
}

$PreMessage = @" 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTML TABLE</title>
<style>
    BODY{background-color:white;}
    TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
    TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:MidnightBlue; color:Yellow}
    TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:PaleGoldenrod}
    TR.D0 TD {background-color: White; color: black;}
    TR.D1 TD {background-color: LawnGreen; color: black;}
    TR.Crit TD {background-color: Red; color: black;}
</style>
</head><body>

"@

$PostMessage = "<br>This script was run by " + $env:username + " on " + $env:COMPUTERNAME
$PostMessage += "<br>ScriptName: $($MyInvocation.MyCommand) "
$PostMessage += "<br>Script path: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"
$PostMessage += "</body></html>"

$HTML = $PreMessage +  $($ModifiedHTML | out-string) + $PostMessage

Send-MailMessage -From $From -To $To -SmtpServer $smtpServer -Attachments $OutputFile `
    -Subject "$Env:userdomain Domain Server Drive Usage Report" -BodyAsHtml $HTML


Disk Free Space Alert

This script will send an email alert for low disk freespace
$MinimumFreePercent = 20
$Alert = $false
$smtpServer = "mail.blah.com"
$To   = "Kevin Curran <kcurran@blah.com>"

$From = "Reporting <Reporting@blah.com>"

$LocalDisks = Get-WmiObject Win32_LogicalDisk -Filter "DriveType='3'" | select DeviceID, 
    @{Name='SizeGB';Expression={[Math]::Round($($_.Size / 1GB),1)}},
    @{Name='FreespaceGB';Expression={[Math]::Round($($_.FreeSpace / 1GB ),1)}},
    @{Name='PercentFree';Expression={[Math]::Round($($_.FreeSpace /$_.Size * 100),1)}} 

Function check-even ($num) {[bool]!($num%2)}
$PreMessage = @" 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTML TABLE</title>
<style>
    BODY{background-color:white;}
    TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
    TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:MidnightBlue; color:Yellow}
    TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}
    TR.D0 TD {background-color: White; color: black;}
    TR.D1 TD {background-color: LawnGreen; color: black;}
</style>
</head><body>

“@
    
foreach ($Drive in $LocalDisks)
{
    IF ($Drive.PercentFree -LT $MinimumFreePercent) {$Alert = $true}
}

If ($Alert) 
{
    
    
    $PostMessage += "<br>This script was run by " + $env:username + " on " + $env:COMPUTERNAME
    $PostMessage += "<br>ScriptName: $($MyInvocation.MyCommand) "
    $PostMessage += "<br>Script path: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"
    $PostMessage += "</body></html>"

    $Message= $LocalDisks | sort -Property DeviceID | ConvertTo-Html -Property DeviceID, SizeGB, FreespaceGB, PercentFree  -PreContent `
        "Please look into the lack of available disk space on this machine. <H2>Local Drives on $($env:COMPUTERNAME) </H2>" | ForEach-Object {$_}

    $ModifiedHTML=ForEach ($line in $Message)
{
    $counter++
    if (check-even $counter)
        {$line.replace('<tr><td>','<tr class="d0"><td>')}
    Else
        {$line.replace('<tr><td>','<tr class="d1"><td>')}
}

$html = $PreMessage + $($ModifiedHTML | out-string) + $PostMessage

    #Send Email
    Send-MailMessage -From $From -To $To -SmtpServer $smtpServer -bodyashtml -Body $html `
        -Subject "$($env:COMPUTERNAME) has at least one disk with less than $MinimumFreePercent% freespace" 
}



Same Alert Via GMail

$MinimumFreePercent = 10
$Alert = $false
$LogFileDir = "C:\Scripts\DiskUsageLogs"
$To = "foo@gmail.com","kevin@blah.com"
$From = "reporting@gmail.com" 
$BadPassword = "badcleartextpassword"

$LocalDisks = Get-WmiObject Win32_LogicalDisk -Filter "DriveType='3'" | select DeviceID, 
    @{Name='SizeGB';Expression={[Math]::Round($($_.Size / 1GB),1)}},
    @{Name='FreespaceGB';Expression={[Math]::Round($($_.FreeSpace / 1GB ),1)}},
    @{Name='PercentFree';Expression={[Math]::Round($($_.FreeSpace /$_.Size * 100),1)}} 

Function check-even ($num) {[bool]!($num%2)} 

Function out-zip { 
  Param([string]$path) 

  if (-not $path.EndsWith('.zip')) {$path += '.zip'} 

  if (-not (test-path $path)) { 
    set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
  } 
  $ZipFile = (new-object -com shell.application).NameSpace($path) 
  $input | foreach {$zipfile.CopyHere($_.fullname)} 

#Log Disk usage to a .csv file to see growth over time
Foreach ($Disk in $LocalDisks)
{
    $LogFilePath = "$LogFileDir\$($env:COMPUTERNAME)_$($Disk.DeviceID.substring(0,1))_DriveUsage.csv"
    write-host $LogFilePath
    If((Test-path $LogFilePath) -eq $false)
    {
        "Date,Drive,SizeGB,FreespaceGB,PercentFree" | Out-File $LogFilePath
    }
    "$(get-date -UFormat "%m/%d/%Y %r"),$($Disk.DeviceID),$($Disk.SizeGB),$($Disk.FreespaceGB),$($Disk.PercentFree)" | Out-File -Append $LogFilePath
    
}

$PreMessage = @" 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTML TABLE</title>
<style>
    BODY{background-color:white;}
    TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
    TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:MidnightBlue; color:Yellow}
    TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}
    TR.D0 TD {background-color: White; color: black;}
    TR.D1 TD {background-color: LawnGreen; color: black;}
</style>
</head><body>

“@
    
foreach ($Drive in $LocalDisks)
{
    IF ($Drive.PercentFree -LT $MinimumFreePercent) {$Alert = $true}
}

If ($Alert) 
{
    $CompressedLogs = "$LogFileDir\CompressedLogs.zip"
    If (test-path $CompressedLogs) {Remove-item $CompressedLogs}
    #Not sure why this fails on multiple files changed it to do foreach file
    #Get-item $LogFileDir\*.csv| out-zip $CompressedLogs
    $Logfiles = Get-item $LogFileDir\*.csv
    foreach ($file in $Logfiles) {get-item $file.fullname | out-zip $CompressedLogs}
    
    
    
    
    $PostMessage += "<br>This script was run by " + $env:username + " on " + $env:COMPUTERNAME
#    $PostMessage += "<br>ScriptName: $($MyInvocation.MyCommand) "
#    $PostMessage += "<br>Script path: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"
    $PostMessage += "</body></html>"

    $Message= $LocalDisks | sort -Property DeviceID | ConvertTo-Html -Property DeviceID, SizeGB, FreespaceGB, PercentFree  -PreContent `
        "Please look into the lack of available disk space on this machine. <H2>Local Drives on $($env:COMPUTERNAME) </H2>" | ForEach-Object {$_}

    $ModifiedHTML=ForEach ($line in $Message)
    {
    $counter++
    if (check-even $counter)
        {$line.replace('<tr><td>','<tr class="d0"><td>')}
    Else
        {$line.replace('<tr><td>','<tr class="d1"><td>')}
    }

    $html = $PreMessage + $($ModifiedHTML | out-string) + $PostMessage

    #Send Email
    #Send-MailMessage -From $From -To $To -SmtpServer $smtpServer -bodyashtml -Body $html `
    #    -Subject "$($env:COMPUTERNAME) has at least one disk with less than $MinimumFreePercent% freespace" 
    
 
    $Subject = "$($env:COMPUTERNAME) has at least one disk with less than $MinimumFreePercent% freespace"  
    $SMTPServer = "smtp.gmail.com" 
    #$SMTPMessage = New-Object System.Net.Mail.MailMessage($From,$To,$Subject,$HTML)
    $SMTPMessage = New-Object System.Net.Mail.MailMessage
    $SMTPMessage.From = $From
    Foreach ($email in $To)
    {
        $SMTPMessage.To.Add($email)
    }
    $SMTPMessage.Subject = $Subject
    $SMTPMessage.body = $HTML
    $SMTPMessage.IsBodyHtml = $true
    $attachment = New-Object System.Net.Mail.Attachment($CompressedLogs)
    $SMTPMessage.Attachments.Add($attachment)
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) 
    $SMTPClient.EnableSsl = $true 
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($From, $BadPassword); 
    $SMTPClient.Send($SMTPMessage)    
}





Comments