Monitoring disk space with simple PowerShell script

I’ve been asked several times in the past about what I typically use to monitor server disk space if the environment I was working in did not have a proper monitoring server or was in the process of deploying one and I’ve always recommended a script I’ve used for quite some time but never blogged about it so I thought it would be great to do so as I could give credit to a script a fellow blogger created as well as demonstrate how to set it up as a task in Task Scheduler.

The PowerShell script I’ve been using for the past few years that works with Windows Server 2008 R2 and 2012 R2 is written by Sean Duffy:

Disk Space Monitoring and Early Warning with PowerShell

https://www.simple-talk.com/sysadmin/powershell/disk-space-monitoring-and-early-warning-with-powershell/

What I like about this script is that it allows you to specify a list servers to monitor in a text file and provides a simple report coloured in red:

image

The way I automate this script is to perform the following steps:

Step #1 – Selec t a server that I would like to execute this PowerShell script on then create the following folder:

C:ScriptsCheckDiskSpace

Step #2 – Create the following 3 files:

image

File #1 – CheckDiskSpace.txt

Copy the following command into this file:

powershell.exe -command “& ‘C:ScriptsCheckDiskSpacediskspace.ps1’ ‘C:ScriptsCheckDiskSpacelist.txt’ “

File #2 – DiskSpace.ps1

Copy the PowrShell script into this file:

————————————————————————————————————————————————————–

#########################################################

#

# Disk space monitoring and reporting script

#

#########################################################

$users = “toaddress@yourdomain.com” # List of users to email your report to (separate by comma)

$fromemail = “fromaddress@yourdomain.com

$server = “yourmailserver.yourdomain.com” #enter your own SMTP server DNS name / IP address here

$list = $args[0] #This accepts the argument you add to your scheduled task for the list of servers. i.e. list.txt

$computers = get-content $list #grab the names of the servers/computers to check from the list.txt file.

# Set free disk space threshold below in percent (default at 10%)

[decimal]$thresholdspace = 10

#assemble together all of the free disk space data from the list of servers and only include it if the percentage free is below the threshold we set above.

$tableFragment= Get-WMIObject -ComputerName $computers Win32_LogicalDisk `

| select __SERVER, DriveType, VolumeName, Name, @{n=’Size (Gb)’ ;e={“{0:n2}” -f ($_.size/1gb)}},@{n=’FreeSpace (Gb)’;e={“{0:n2}” -f ($_.freespace/1gb)}}, @{n=’PercentFree’;e={“{0:n2}” -f ($_.freespace/$_.size*100)}} `

| Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace} `

| ConvertTo-HTML -fragment

# assemble the HTML for our body of the email report.

$HTMLmessage = @”

<font color=””black”” face=””Arial, Verdana”” size=””3″”>

<u><b>Disk Space Storage Report</b></u>

<br>This report was generated because the drive(s) listed below have less than $thresholdspace % free space. Drives above this threshold will not be listed.

<br>

<style type=””text/css””>body{font: .8em “”Lucida Grande””, Tahoma, Arial, Helvetica, sans-serif;}

ol{margin:0;padding: 0 1.5em;}

table{color:#FFF;background:#C00;border-collapse:collapse;width:647px;border:5px solid #900;}

thead{}

thead th{padding:1em 1em .5em;border-bottom:1px dotted #FFF;font-size:120%;text-align:left;}

thead tr{}

td{padding:.5em 1em;}

tfoot{}

tfoot td{padding-bottom:1.5em;}

tfoot tr{}

#middle{background-color:#900;}

</style>

<body BGCOLOR=””white””>

$tableFragment

</body>

“@

# Set up a regex search and match to look for any <td> tags in our body. These would only be present if the script above found disks below the threshold of free space.

# We use this regex matching method to determine whether or not we should send the email and report.

$regexsubject = $HTMLmessage

$regex = [regex] ‘(?im)<td>’

# if there was any row at all, send the email

if ($regex.IsMatch($regexsubject)) {

send-mailmessage -from $fromemail -to $users -subject “Disk Space Monitoring Report” -BodyAsHTML -body $HTMLmessage -priority High -smtpServer $server

}

# End of Script

————————————————————————————————————————————————————–

File #3 – List.txt

Type in the list of servers you would like to monitor:

image

Step #3 – Configure the variables in the scripts

Open the DiskSpace.ps1 script and modify the email address the report should be send from and to, the server name of the SMTP server that will be sending the email, the % for the threshold you would like to set for the free disk space.

What I usually do as a test is to set the threshold to 50% so that an email would get fired off during the initial setup allowing me to confirm that all the variables are set up properly.

Step #4 – Fill in the List.txt file with server FQDNs

As shown in the screenshot above, proceed by adding in the FQDNs of the servers you will be monitoring with this script.

Step #5 – Test Script

Open the CheckDiskSpace.txt then copy the command in the file:

powershell.exe -command “& ‘C:ScriptsCheckDiskSpacediskspace.ps1’ ‘C:ScriptsCheckDiskSpacelist.txt’ “

… and paste it into a command prompt to confirm that an email alert is generated and sent to the email address you’ve specified.

Step #6 – Configure scheduled task to execute the script

Launch the task schedule and create a new task:

image

Provide a name for the Task:

image

Configure the task to Run whether user is logged on or not and Run with the highest privileges:

image

Click on the Triggers tab and create a new Trigger based on your requirements:

image

Click on the Actions tab and create a new Action with the following configuration:

Program/script: powershell.exe

Add arguments (optional): -command “& ‘C:ScriptsCheckDiskSpacediskspace.ps1’ ‘C:ScriptsCheckDiskSpacelist.txt’ “

image

Save the configuration and you should now see a new task configured:

image

You can test the task by right clicking on the line item and selecting Run:

image

5 Responses

  1. Can I get it to just show the C: drive and not say the page file drive P:?

    Great script! Thanks!!

  2. I found it – modified line 27 to Get-WmiObject -ComputerName $computers Win32_LogicalDisk -filter "DeviceID='C:'"`

    The filter will give you whatever drive letter you want to look at.

    Mark

  3. hi
    i have tested with line from cmd and I'm getting this error:

    C:SCRIPTS>powershell.exe -command "& 'C:ScriptsCheckDiskSpacediskspace.ps1' 'C:ScriptsCheckDiskSpacelist.txt' "
    send-mailmessage : The SMTP server requires a secure connection or the client was not authenticated. The server
    response was: 5.7.0 Must issue a STARTTLS command first. h12sm25224952oan.14 – gsmtp
    At C:ScriptsCheckDiskSpacediskspace.ps1:50 char:1
    + send-mailmessage -from $fromemail -to $users -subject "Disk Space Mon …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
    ion
    + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage

    Well, I know this is about auth. My smtp server is smtp.gmail.com. How and where should I change the code in order to put the password on the ps1 script?
    thank you

  4. I copied this script but while running the command getting below errors. Could you please let me know how we can fix this issue? I copied this code from this blog.

    At D:ScriptsCheckDiskSpacediskspace.ps1:31 char:1
    $+ |select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)';e={"{0 …
    + ~
    An empty pipe element is not allowed.
    At D:ScriptsCheckDiskSpacediskspace.ps1:86 char:28
    + $regex = [regex] '
    + ~
    The string is missing the terminator: '.
    At D:ScriptsCheckDiskSpacediskspace.ps1:86 char:24
    + $regex = [regex] '
    + ~
    The '<' operator is reserved for future use.
    At D:ScriptsCheckDiskSpacediskspace.ps1:1 char:1
    + ——————————————————————— …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The assignment expression is not valid. The input to an assignment operator must be an object that is able to accept
    assignments, such as a variable or a property.
    At D:ScriptsCheckDiskSpacediskspace.ps1:1 char:3
    + ——————————————————————— …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The '–' operator works only on variables or on properties.
    At D:ScriptsCheckDiskSpacediskspace.ps1:1 char:5
    + ——————————————————————— …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The '–' operator works only on variables or on properties.
    At D:ScriptsCheckDiskSpacediskspace.ps1:1 char:7
    + ——————————————————————— …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The '–' operator works only on variables or on properties.
    At D:ScriptsCheckDiskSpacediskspace.ps1:1 char:9
    + ——————————————————————— …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The '–' operator works only on variables or on properties.
    At D:ScriptsCheckDiskSpacediskspace.ps1:1 char:11
    + ——————————————————————— …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The '–' operator works only on variables or on properties.
    At D:ScriptsCheckDiskSpacediskspace.ps1:1 char:13
    + ——————————————————————— …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The '–' operator works only on variables or on properties.
    Not all parse errors were reported. Correct the reported errors and try again.
    + CategoryInfo : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : EmptyPipeElement