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:
Implementation, 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!
Categories: Cyber Security, PowerShell, Windows Server
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
LikeLike
Hi,
Yes. Just modify the filter to target your sql servers based on their names or something else.
LikeLike
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)
LikeLiked 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!
LikeLike
Thank you for your kind comment and the tip!
LikeLike
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
LikeLike
Hi, you
shouldn’t happen. I used 0.1 and it worked fine.
Best
P
LikeLike
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 😉 🙂 🙂
LikeLike
Could you please ,PowerShell: Alert me when Virtual Machine is running more than “X” hrs in a day to get E-Mail Notification?
LikeLike
Good idea! However, this is very special and will address only a few.
LikeLike
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)
LikeLike
What about san connected drives?
LikeLike
This is nice script. I am wondering how to add multiple recipients?
LikeLike
Separate e-mail addresses by comma, or create a distribution group.
All the best,
P
LikeLike