Today I would like to share with our readers RunningLow, a simple yet effective PowerShell script I coded a while ago to get to know when one of my servers is running low of disk space.
Whoever works with physical and/or virtualized Windows Servers is well aware of the importance of keeping this constantly under control: as soon as a server runs out of disk space it will be unable to fullfill a number of tasks, such as: create temporary files, store data on a database, performing system maintenance / backup / updates, create or update web sessions - assuming they are handled through I/O - and so on. Things can be even worse for those servers who host DBMS services such as MySQL and MS-SQL, as the sudden I/O unavailability could cause non-trivial damages to indexes, filesystem-based tables and data integrity.
The main purpose of RunningLow is to prevent all that: it will check one or more local and/or network drives to see if their available free space went under a certain quota, and send a customizable alert to one or more e-mail addresses if that's the case. I know, there are A LOT of admin suites and maintenance software that could be easily configured to the same thing: even Piriform's CCleaner PRO does that! However, if you don't have the money, the time or the amount of system resources required to install these apps, you might find out that this lightweight alternative could be worth a shot.
Source Code
Anyway, here's the script source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# Drives to check: set to $null or empty to check all local (non-network) drives # $drives = @("C","D"); $drives = $null; # The minimum disk size to check for raising the warning $minSize = 20GB; # SMTP configuration: username, password & so on $email_username = "username@yourdomain.com"; $email_password = "yourpassword"; $email_smtp_host = "smtp.yourdomain.com"; $email_smtp_port = 25; $email_smtp_SSL = 0; $email_from_address = "username@yourdomain.com"; $email_to_addressArray = @("to1@yourdomain.com", "to2@yourdomain.com"); if ($drives -eq $null -Or $drives -lt 1) { $localVolumes = Get-WMIObject win32_volume; $drives = @(); foreach ($vol in $localVolumes) { if ($vol.DriveType -eq 3 -And $vol.DriveLetter -ne $null ) { $drives += $vol.DriveLetter[0]; } } } foreach ($d in $drives) { Write-Host ("`r`n"); Write-Host ("Checking drive " + $d + " ..."); $disk = Get-PSDrive $d; if ($disk.Free -lt $minSize) { Write-Host ("Drive " + $d + " has less than " + $minSize ` + " bytes free (" + $disk.free + "): sending e-mail..."); $message = new-object Net.Mail.MailMessage; $message.From = $email_from_address; foreach ($to in $email_to_addressArray) { $message.To.Add($to); } $message.Subject = ("[RunningLow] WARNING: " + $env:computername + " drive " + $d); $message.Subject += (" has less than " + $minSize + " bytes free "); $message.Subject += ("(" + $disk.Free + ")"); $message.Body = "Hello there, `r`n`r`n"; $message.Body += "this is an automatic e-mail message "; $message.Body += "sent by RunningLow Powershell script "; $message.Body += ("to inform you that " + $env:computername + " drive " + $d + " "); $message.Body += "is running low on free space. `r`n`r`n"; $message.Body += "--------------------------------------------------------------"; $message.Body += "`r`n"; $message.Body += ("Machine HostName: " + $env:computername + " `r`n"); $message.Body += "Machine IP Address(es): "; $ipAddresses = Get-NetIPAddress -AddressFamily IPv4; foreach ($ip in $ipAddresses) { if ($ip.IPAddress -like "127.0.0.1") { continue; } $message.Body += ($ip.IPAddress + " "); } $message.Body += "`r`n"; $message.Body += ("Used space on drive " + $d + ": " + $disk.Used + " bytes. `r`n"); $message.Body += ("Free space on drive " + $d + ": " + $disk.Free + " bytes. `r`n"); $message.Body += "--------------------------------------------------------------"; $message.Body += "`r`n`r`n"; $message.Body += "This warning will fire when the free space is lower "; $message.Body += ("than " + $minSize + " bytes `r`n`r`n"); $message.Body += "Sincerely, `r`n`r`n"; $message.Body += "-- `r`n"; $message.Body += "RunningLow`r`n"; $message.Body += "https://www.ryadel.com/RunningLow"; $smtp = new-object Net.Mail.SmtpClient($email_smtp_host, $email_smtp_port); $smtp.EnableSSL = $email_smtp_SSL; $smtp.Credentials = New-Object System.Net.NetworkCredential($email_username, $email_password); $smtp.send($message); $message.Dispose(); write-host "... E-Mail sent!" ; } else { Write-Host ("Drive " + $d + " has more than " + $minSize + " bytes free: nothing to do."); } } |
Copy/paste it into a text file, save it to RunningLow.ps1 (or any other name) and you should be set. Alternatively, you can also download the latest version from the project's official GitHub repo.
Configuration
The first ten or so lines host the configuration settings, which you should change accordingly to your needs and depending to your specific scenario. The most important thing to understand is the first line: as we can see, we can either specify an array of drives - including network drives, as long as they're permanently mapped to a local drive letter - or set a null value: if we go for the latter, the script will check all local drives.
The comments should be enough to guide you through this required part: however, if you need further assistance, you can use the comment section of this post to submit your query and I'll do my best to help you with that.
Testing
As soon as you're done with the configuration, you can test the script from the standard Windows Command Prompt with the following command:
1 |
> powershell -executionpolicy bypass -File RunningLow.ps1 |
... Or by typing
.\RunningLow.ps1from a PowerShell prompt.
As soon as you hit ENTER, you should see something like this:
... Meaning that everything went ok.
Sending E-Mail Alerts
Needless to say, you should then edit the script, raise the $minSize value to a ridiculously high amount (such as 5TB) and run another test to ensure that the e-mail alerts will actually be sent:
... That's it.
Installing
It goes without saying that the script should not be launched manually: the best thing we can do to ensure that it will be executed on regular basis is to create an appropriate entry in the Windows Task Scheduler. In the example below, RunningLow will be executed once a day at noon:
In the New Action window you can either insert the full execution statement (including parameters) in the Program/script textbox, or use the Add arguments (optional) textbox: the script will work either way. Similarly, you can specify the full path of the RunningLow.ps1 file within the -File parameter or put it into the Start in (optional) textbox, just like we did in the above screenshot.
IMPORTANT: In the scheduled task General tab, be sure to activate the options Run whether the user is logged on or not and Run with highest priviledges, otherwise the script would run only if there's a logged-in user during the execution time.
Be sure to test it again - by setting an insanely high $minSize - on the server as well, to be sure that there are no firewalls or other restrictions that would block the e-mail alerts.
Well, that's it for now: I sincerely hope that you will enjoy having RunningLow on your servers just like I do!
Useful Links
- RunningLow official repository on GitHub.