Cyber Security

PowerShell: Alert me when Disk Space is running low on my Windows Servers (E-Mail Notification)

Without any doubt, you should have an eye on the disk space of your servers. I’ve seen so many servers crashing due to dropping disk space over time, because of saving more and more files and data or because of Windows Updates. They were running Exchange, SQL, AD and all of them were important servers with crucial software on it. If you are currently not monitoring disk free spaces and if you don’t have an enterprise tool like SCCM at hand then this article is for you. We do it all with PowerShell, what else? Let’s jump in.

As mentioned, the goal is to implement a monitoring solution to monitor all Windows Servers. To achieve this, we need a couple of things:

  • All Windows Server by Name (best with a cleaned up Active Directory environment, with no orphaned computer accounts)
  • A foreach loop with Get-WmiObject win32_logicaldisk to get disk free space from all servers
  • An if statement in the loop to get only notified of servers with low disk space
  • E-Mail Configuration (maybe with a password in it, be sure, I will take care of this problem and provide you a solution)

The Goal

Defining the goal is easy. We want to get an E-Mail when one of the server is running on low disk space. The E-Mail should look like this:

Capture.PNGImplementation, on the other hand, is a little more difficult. This brings me to the script.

The Script

The following script alerts you if one of your servers has less than 10 % disk space.


### Getting all domain-joined Server by Names

$servers=(Get-ADComputer -Filter 'operatingsystem -like "*server*"').Name

### Get only DriveType 3 (Local Disks) foreach Server

ForEach ($s in $servers)

{$Report=Get-WmiObject win32_logicaldisk -ComputerName $s -Filter "Drivetype=3" -ErrorAction SilentlyContinue | Where-Object {($_.freespace/$_.size) -le '0.1'}
$View=($Report.DeviceID -join ",").Replace(":","")
### Send Mail if $Report (<=10%) is true

If ($Report)

{

$EmailTo = "p.gruenauer@domain.xy"
$EmailFrom = "alert@domain.xy"
$user = 'p.gruenauer@domain.xy'
$password = Unprotect-CmsMessage -Path C:\Temp\pw.txt
$Subject = "Alert: PowerShell Storage Report of $s"
$Body = "Server $s storage space has dropped to less than 10 % on $View"
$SMTPServer = "smtp.domain.xy"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($user, $password)
$SMTPClient.Send($SMTPMessage)

}

}

You have to edit line 17,18,19,20 and 23 to your fits.

Line 20 is very interesting. For sending an E-Mail you usually have to authenticate your account to the E-Mail server. This also means that the password has to be saved in your script. To avoid this, encrypt the password file as described here PowerShell: Encrypt and Decrypt Data by using Certificates (Public Key / Private Key)

Unprotect-CmsMessage decrypts the file’s content. Remember that you are hopefully the only one who has the private key and therefore you are the only one on this planet who can decrypt the password file.

If you like it, copy it into your PowerShell ISE session and save it as C:\PowerShell\alert_diskspace.ps1.

Create a Scheduled Task

Finally we will wrap up our script into a Scheduled Task that runs every day.

The lines below create a scheduled task that runs C:\PowerShell\alert_diskspace.ps1 once a day (08:00 am).

You may want to edit the file path in line 1 and you have to modify the UserId in line 4.


$Action=New-ScheduledTaskAction -Execute "powershell" -Argument "C:\PowerShell\alert_diskspace.ps1"
$Trigger=New-ScheduledTaskTrigger -Daily -At 08am
$Set=New-ScheduledTaskSettingsSet
$Principal=New-ScheduledTaskPrincipal -UserId "sid-500\patrick" -LogonType S4U
$Task=New-ScheduledTask -Action $Action -Trigger $Trigger -Settings $Set -Principal $Principal -Description "Checks free disk space on all Servers. Sends an E-Mail notification if storage drops below 10%"
Register-ScheduledTask -TaskName "Free Disk Space Check" -InputObject $Task -User "sid-500\patrick" -Password (Read-Host 'Enter Password') -Force

That’s it. Your severs are monitored.

See you next time with PowerShell again!

28 replies »

  1. Is there a way to specify a list database servers in a text file (I.e. Servers.txt) in the first statement: $servers=(Get-ADComputer -Filter ‘operatingsystem -like “*server*”‘).Name

    I just want to report on sql server database servers.

    Thanks for the helpful script.

    Kevin

    Like

      • Thanks Patrick. I was able to get your script to work by modifying the filter. It sends an email to myself. But, it is not sending the email to a group email address. I commented out the below statement. Does this statement has anything to do with sending emails to a group or multiple email addresses? It appears this statement is not needed. If I don’t use the group email address and specify multiple email addresses should I separate them with a comma, colon, etc.? I tried a comma and that appears to not have worked. I will continue to play with it.

        $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($user, $password)

        Liked by 1 person

      • I got it to work following the suggestion in this article: Powershell script unable to send to multiple recipients
        https://stackoverflow.com/questions/15256862/powershell-script-unable-to-send-to-multiple-recipients

        # NOTE: Note: Send-MailMessage was introduced in PowerShell v2.0 so that’s why there are still examples that use other commands.

        The below statement worked for me:
        Send-MailMessage -from $From -To $To -Subject $Subject -Body $Body -smtpServer $SMTPServer

        Thanks again for the script Patrick!

        Like

  2. Hi Patrick,
    it works so far, but it can happen that the disks get full before the emailalert job has to be done. In this case the server stops bevor I knot it :/
    So I changed the setup from “.1” to “.12″ or to”.15″ but then I’ve got mails even if the free disc space is very high.
    Any idea?

    Kind regards
    Vic

    Like

      • hi Patrick ,
        i have a problem, with automating script to remove the old updates (cache) in disk i have fonction but the problem how to automate this fonction with program , if you have any idea to help me in this situation thank you 😉 🙂 🙂

        Like

  3. Could you please ,PowerShell: Alert me when Virtual Machine is running more than “X” hrs in a day to get E-Mail Notification?

    Like

  4. Is there a way to just enter the smtp password into the script? I’m not trying to setup security keys for this (I know, I know)

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.