Low Disk Space Alert for SQL Server

By:   |   Comments (32)   |   Related: > Monitoring


Problem

SQL Server Database Administrators do not always have tools in place for monitoring free disk space. One option are these PowerShell scripts for monitoring disk space, but I am an overloaded SQL Server DBA and need a low disk space alert for SQL Server to automate the monitoring and notification process. Can you provide any recommendations?

Solution

In this tip we will provide steps for automated email notifications when disk space is lower than a specified threshold. To accomplish this we will setup a SQL Server Agent Job that executes the previously mentioned PowerShell script. The PowerShell script will check the disk space based on the threshold parameters passed to the code. Then, if the disk space is lower than the threshold, the script will send a formatted email to the address you specify.

Keep in mind SQL Server should be able to send emails in order for the script to work properly and parameters from this script need to be updated to your specific environment.

PowerShell script

# Replace "smtp.domain.com" with your mail server name
$smtp=new-object Net.Mail.SmtpClient("smtp.domain.com")

# Set thresholds (in gigabytes) for C: drive and for the remaining drives
$driveCthreshold=10
$threshold=60


# Replace settings below with your e-mails
$emailFrom="[email protected]"
$emailTo="[email protected]"

# Get SQL Server hostname
$hostname=Get-WMIObject Win32_ComputerSystem | Select-Object -ExpandProperty name

# Get all drives with free space less than a threshold. Exclude System Volumes
$Results = Get-WmiObject -Class Win32_Volume -Filter "SystemVolume='False' AND DriveType=3"|
  Where-Object {($_.FreeSpace/1GB –lt  $driveCthreshold –and $_.DriveLetter -eq "C:")`
 –or ($_.FreeSpace/1GB –lt  $threshold –and $_.DriveLetter -ne "C:" )}

ForEach ($Result In $Results)
{
    $drive = $Result.DriveLetter
    $space = $Result.FreeSpace
    $thresh = if($drive -eq 'C:'){$driveCthreshold} else {$threshold}

    # Send e-mail if the free space is less than threshold parameter 
    $smtp.Send(
	$emailFrom, 
	$emailTo, 
	# E-mail subject
	"Disk $drive on $hostname has less than $thresh GB of free space left ",
	# E-mail body 
	("{0:N0}" -f [math]::truncate($space/1MB))+" MB")
}

The script above checks free space based on two different thresholds - one for the system drive (C:) and another one for the rest of the drives. We are using 10GB for the C: drive and 60GB for the other drives for this demo. Setup the thresholds based on your database growth rate or remaining disk space.

PowerShell Formatting and Conversion Options

In our script we used byte conversion to check the disk space in gigabytes versus bytes when compared against the threshold (which is in gigabytes):

Where-Object {......
$_.FreeSpace/1GB –lt  $threshold ......}

Also, we used the "Truncate" method from the [math] class to strip off the decimal points. Note, that we wanted to display the result in the e-mail body in megabytes:

[math]::truncate($space/1MB)

Then, we used .Net formatting to display number with comma for thousands: "16,837 MB".

"{0:N0}" -f [math]::truncate($space/1MB)

Read more about "-f" format operator here.

Read more about PowerShell formatting here.

Create SQL Server Agent job

Now we will create an SQL Server Agent Job that will be executing this PowerShell script. Select "PowerShell" as a job's step type:

Email Alert

Here is a sample e-mail that will be sent if any of the drives have less free disk space than the specified thresholds:

Email Alert

Read SQL Server Agent tips to find more details on how to setup the jobs.

Next Steps
  • Make sure you monitor your SQL Servers disk space either with third party monitoring tools or with custom scripts.
  • Find more PowerShell tips here.
  • Read other tips about checking disk space here and here.
  • Read this tip about determining free disk space with T-SQL.
  • Read other tips about SQL Server Monitoring.


sql server categories

sql server webinars

subscribe to mssqltips

sql server tutorials

sql server white papers

next tip



About the author
MSSQLTips author Svetlana Golovko Svetlana Golovko is a DBA with 13 years of the IT experience (including SQL Server and Oracle) with main focus on performance.

This author pledges the content of this article is based on professional experience and not AI generated.

View all my tips



Comments For This Article




Wednesday, December 8, 2021 - 6:18:49 PM - Svetlana Back To Top (89554)
To calculate free space in percent you can use "Capacity" and "FreeSpace" properties of the Win32_Volume class.

Wednesday, December 8, 2021 - 5:39:01 PM - Svetlana Golovko Back To Top (89553)
The notification with "0 MB" means there IS a problem and 0 MB of space left.

Wednesday, December 1, 2021 - 8:16:26 AM - Ses Back To Top (89508)
Hi Svetlana,

Script is useful for me..but i want % instead of GB. could you provide that.

Tuesday, November 30, 2021 - 9:00:41 PM - Seshu Back To Top (89504)
Hi Svetlana,

I used above script..but when job running getting notification in body 0 MB..I want alert only when space issue only..could you suggest on this...

Sunday, January 5, 2020 - 4:09:43 PM - Svetlana Back To Top (83634)

 $Results = Get-WmiObject -Class Win32_Volume -Filter "SystemVolume='False' AND DriveType=3"|

  Where-Object {(($_.FreeSpace/1GB –lt  $driveCthreshold –and $_.DriveLetter -eq "C:")`
 –or ($_.FreeSpace/1GB –lt  $threshold –and $_.DriveLetter -ne "C:" ) -and $_.DriveLetter -ne "M:")}

Friday, January 3, 2020 - 3:02:35 PM - Kapil Swamy Back To Top (83619)

Please confirm syntax to exclude the quorum drive eg M

$Results = Get-WmiObject -Class Win32_Volume -Filter "SystemVolume='False' AND DriveType=3"|
  Where-Object {($_.FreeSpace/1GB –lt  $driveCthreshold –and $_.DriveLetter -eq "C:")`
 –or ($_.FreeSpace/1GB –lt  $threshold –and $_.DriveLetter -ne "C:" )}

Thursday, January 2, 2020 - 5:06:30 PM - Svetlana Back To Top (83604)

 Hi Kapil,

You can do it in 2 different ways - add a filter to this part to exclude the drive:

$Results = Get-WmiObject -Class Win32_Volume -Filter "SystemVolume='False' AND DriveType=3"|
  Where-Object {($_.FreeSpace/1GB –lt  $driveCthreshold –and $_.DriveLetter -eq "C:")`
 –or ($_.FreeSpace/1GB –lt  $threshold –and $_.DriveLetter -ne "C:" )}

or add another condition for the equorum drive similar to the $driveCthreshold for C: drive.
Thanks,
Svetlana

Thursday, January 2, 2020 - 4:35:37 AM - Kapil Swamy Back To Top (83594)

The job is raising alert for MSDTC drive having 1 GB disk space. How can I exclude the MSDTC or quorrum drives?


Wednesday, June 12, 2019 - 12:52:40 PM - Lee Back To Top (81443)

Svetlana,

Thank you fore the reply. I put it on my dev edition on my PC and it ran just fine so there is something on our servers that won't allow the powershell to send email. DBMail works just fine.

Lee T.


Wednesday, June 12, 2019 - 11:48:42 AM - Svetlana Back To Top (81438)

Hi Lee,

The assumption in this tip is that SMTP server uses port 25 (your server might use a different port). Also, if your organization needs to "whitelist" the servers that send emails you may experience issues as well. Some configurations require using credentials. You may need to work with your Mail support team to troubleshoot and to get the correct SMTP settings.

See the example that uses more smtp settings here: https://stackoverflow.com/questions/37563990/powershell-error-on-sending-e-mail

Thanks,

Svetlana


Tuesday, June 11, 2019 - 7:18:24 PM - Lee Back To Top (81422)

I am having the same issue as Kevin with the following error:

A job step received an error at line 28 in a PowerShell script. The corresponding line is '    $smtp.Send('. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Exception calling "Send" with "4" argument(s): "Failure sending mail."  '.  Process Exit Code -1.  The step failed.

I have verified that I have to correct SMTP Server address in there.  I have tried the IP address as well.  Don't know what to do at this point.

Thank you,

Lee


Thursday, July 26, 2018 - 8:39:48 AM - Svetlana Golovko Back To Top (76837)

 Hi Manish

I use this as a schedule driven job, but if you want to get an automated email when your databases grow you can trigger this job with WMI event. The example is here: https://www.mssqltips.com/sqlservertip/3128/monitor-sql-server-database-file-growth-with-wmi-alerts/. It won't trigger the job if somebody copies to the disk large backup though. 

Thanks for reading

Svetlana


Thursday, July 26, 2018 - 6:14:54 AM - Manish Back To Top (76835)

i have create a job but didn't get alert mail, hence my disk was gone thresh hold , do we needs to create schedule or it will run atomatic once its rich to thresh hold..???? please suggest 

i mean is it schedule based or auto if drive rich to thresh hold limit ??


Friday, June 22, 2018 - 4:35:13 AM - Pradeep Back To Top (76282)

 Hi,

I have used this Powershell Script in my prodcution servers and it is working great.

On one of the server, I am receiving email with null paramenters like "Low Disk Space Alert:- 'Disk ' on 'XXXXXXXXXX' has less than '20 GB' of free space left " with no disk name and no remaining space.

Please help me to resolve this.

Thanks in advance.

Regards,

Pradeep


Wednesday, June 29, 2016 - 10:59:58 AM - Kevin Back To Top (41784)

 Nevermind, I found the issue.  It was a misconfiguration of my Net.Mail.SmtpClient

 

Thanks for the script!  It is working great now.

Kevin

 


Wednesday, June 29, 2016 - 10:24:13 AM - Kevin Back To Top (41783)

Svetlana,
When I run the script, I recieve the following error:

A job step received an error at line 28 in a PowerShell script. The corresponding line is '    $smtp.Send('. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Exception calling "Send" with "4" argument(s): "Failure sending mail."  '.  Process Exit Code -1.  The step failed.

.

 

I am not really all that versed in PowerShell, so I am a bit stuck.
Do you have any suggestions?

Kevin

 


Tuesday, January 26, 2016 - 3:59:26 PM - Svetlana Golovko Back To Top (40509)

 
Hi,

The script already sends alerts only when available space is below the specified threshold. You may need to modify the thresholds to your own values:

 

$driveCthreshold=10
$threshold=60

 

$driveCthreshold  - the threshold for the C: drive.

$threshold - for the rest of the drives.

 

Thanks,

Svetlana

 


Monday, January 25, 2016 - 2:12:20 PM - Awhyoh T. Back To Top (40497)

Hello

 

Huge thanks for the script. I would like to know how to go about updating script so that an alert email is sent only when available space is below the specified threshold. Thaks again for the script.

 


Saturday, October 3, 2015 - 7:00:15 PM - Svetlana Back To Top (38822)

Hi Dennis,

 

I am pretty sure you are looking at the job's properties.

You need to create the new job step and then you will see the options that are displayed on the screenshot.

 

Thanks,

Svetlana


Thursday, October 1, 2015 - 7:40:46 AM - Dennis S. Back To Top (38800)

Hi, I thank you for your tip, but when I try to add the job, my options are not the same as your article.  Instead of "Type" I have "Category".  ??  I have SQL Server 2008 R2 Standard.  I can't find any place to enter the PowerShell code...

 


Friday, September 18, 2015 - 2:59:03 PM - Chad Churchwell Back To Top (38715)

adinarayana -

If you have a central management server (CMS) set up and all your servers registered you could easily have an SSIS package that queries all the registered servers from the CMS, and dynamically connects to each one and runs the script.  You would need to save this off into a central repository database, then lay an SSRS report on top of that table for enterprise wide results reporting.

This is one way, there are several others but I think the process is common, just implementation is different.  Your server list could be in a txt file, database table, etc.  I like CMS.

Here is a link to get you started with CMS

https://msdn.microsoft.com/en-us/library/bb934126(v=sql.110).aspx

Here is the query I use to get all my registered servers after CMS is set up

SELECT
--DISTINCT groups.name AS 'Server Group Name',
svr.server_name AS 'Server Name'
FROM msdb.dbo.sysmanagement_shared_server_groups_internal groups
INNER JOIN msdb.dbo.sysmanagement_shared_registered_servers_internal svr
ON groups.server_group_id = svr.server_group_id
WHERE groups.name <> 'Offline'

 


Friday, September 18, 2015 - 7:52:36 AM - adinarayana Back To Top (38707)

Hi ,

 

can i scheduled this script for centralized sql server to get the drive space report to accross all the server at a time


Monday, September 14, 2015 - 11:31:32 AM - Svetlana Golovko Back To Top (38676)

Craig,

This will not work with mount points.


Monday, September 14, 2015 - 11:27:26 AM - Svetlana Golovko Back To Top (38675)

Hi Pratheesh,

 

I am not familiar with "Professional" edition. I am not sure if you got the right edition's name.

You can run this statement to find to find out what edition you have: SELECT SERVERPROPERTY('Edition')

But regardless the edition if you can create a job then you should be able to specify a type of the Job Step (not the Job, the Step itself).

 

 

 

 

 

 


Sunday, September 13, 2015 - 3:22:32 AM - Pratheesh Back To Top (38663)

Thank you for your tip on creating power shell script to validate disk space, but I am facing an issue, in my SQL 2012 Professinal edition, I am not getting the dropdown for Type, Instead I have the drop down for category. Is there any seperate configuration for this? I


Thursday, September 10, 2015 - 3:42:20 PM - Craig Silvis Back To Top (38639)

For more granular control over all drives I did this:

$arrayDriveLetterThresholds  =  ("A:",10),("B:",10),("C:",10),("D:",10),("E:",10),("F:",10);

$arrayDriveLetterThresholds += ,("G:",10),("H:",10),("I:",10),("J:",10),("K:",10),("L:",10);

$arrayDriveLetterThresholds += ,("M:",10),("N:",10),("O:",10),("P:",10),("Q:",10),("R:",10);

$arrayDriveLetterThresholds += ,("S:",10),("T:",10),("U:",10),("V:",10),("W:",10),("X:",10);

$arrayDriveLetterThresholds += ,("Y:",10),("Z:",10);

 

# Get SQL Server hostname

$hostname=Get-WMIObject Win32_ComputerSystem | Select-Object -ExpandProperty name;

 

$emailFrom="[email protected]";

$emailServer = "smtp.example.com";

$emailTo="[email protected]";

 

# Get all drives with free space less than a threshold. Exclude System Volumes

$Results = Get-WmiObject -Class Win32_Volume -Filter "SystemVolume='False' AND DriveType=3";

 

ForEach ($Result In $Results)

{

    $drive = $Result.DriveLetter;

    $space = $Result.FreeSpace/1GB;

    foreach($valuePair in $arrayDriveLetterThresholds)

    {

        if(($drive -eq $valuePair[0]) -and ($space -lt $valuePair[1]))

        {

            $currentThreshold = $valuePair[1];

            $emailSubject = "Disk $drive on $hostname has less than $currentThreshold GB of free space left!";

            $emailBody = "`r`n" + $emailSubject + "`r`nCurrent amount of free space on drive $drive = " + [math]::truncate($space).ToString() + " GB.";

            Send-MailMessage -From $emailFrom -To $emailTo -Subject $emailSubject -Body $emailBody -Priority High -SmtpServer $emailServer;

        }; 

    };

};

 

Thursday, September 10, 2015 - 8:07:45 AM - Svetlana Back To Top (38636)

Murugan

You may need to create a proxy for the PowerShell and run the job as this proxy account (not as SQL Agent). The login used for the proxy must have permissions to run WMI queries on the server.


Thursday, September 10, 2015 - 1:54:40 AM - Murugan Back To Top (38631)

I'm getting the below error while running the job;

 

Message

Executed as user: ---\SYSTEM. The job script encountered the following errors. These errors did not stop the script:  A job step received an error at line 14 in a PowerShell script. The corresponding line is '$hostname=Get-WMIObject Win32_ComputerSystem | Select-Object -ExpandProperty name'. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Cannot expand property "name" because it has nothing to expand.  '  A job step received an error at line 17 in a PowerShell script. The corresponding line is '$Results = Get-WmiObject -Class Win32_Volume -Filter "SystemVolume='False' AND DriveType=3"|'. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Invalid query   '  A job step received an error at line 25 in a PowerShell script. The corresponding line is '    $thresh = if($drive -eq 'C:'){$driveCthreshold} else {$threshold}'. Correct the script and reschedule the job. The error information returned by PowerShell is: 'The term 'if' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.  '.  Process Exit Code -1.  The step failed.


Wednesday, September 9, 2015 - 7:46:51 PM - Svetlana Back To Top (38628)

Hi Chad,

 

Yes, it works with mount points, but you will need to replace

$drive = $Result.DriveLetter

 

with

$drive = $Result.Name

or

$drive = $Result.Caption

to have the correct drive name in the e-mail subject


Wednesday, September 9, 2015 - 5:07:03 PM - Bruce Back To Top (38627)

Victor - Yes, you can use the task scheduler to run a version of this. You would need to specify the -ComputerName for Get-WMIObject. You could put all your servers in an active directory group and then pull them from AD or you can create a table or text file and read from them and iterate through them. Just beware, you'll need to create an excpetion in your firewall to allow powershell to send email. In my current environment our hardware firewall won't permit powershell to send emails, so you might have to either use the sql agent, smo + sp_send_dbmail, or an email client to get around those rules (you can create outlook objects in powershell).

Chad - Get-WMIObject win32_Volume pulls the volume information (disks and mount points), Get-WMIObject win32_LocalDisk will only get disks.


Wednesday, September 9, 2015 - 12:33:48 PM - Victor Sturm Back To Top (38626)

Would it be possible to run this PowerShell script outside of SQL?

I am not only a SQL admin, but our network and server admin in general. I think this script would have uses outside of just SQL particularly in a Virtual environment.

 

Thanks.

Victor


Wednesday, September 9, 2015 - 10:06:56 AM - Chad Churchwell Back To Top (38622)

Very nice solution, quick question, does it work with Mount Points?















get free sql tips
agree to terms