Powershell/NRPE/Check_diskdefragstatus.ps1
2023-07-04 12:59:44 +02:00

181 lines
6.8 KiB
PowerShell

<#
.SYNOPSIS
Check Windows disks fragmentation status.
.DESCRIPTION
Check Windows disks fragmentation status.
Optionally performs defragmentation.
.OUTPUTS
OK: All disk fragmentation status is ok.
WARNING: % of fragmentation equal to Warning treshold.
CRITICAL: % of fragmentation equal to Critical treshold.
.PARAMETER warning
% of fragmentation for warning treshold.
Default System default.
.PARAMETER critical
% of fragmentation for critical treshold.
Default None.
.PARAMETER disks
Disks to check fragmentation status.
Default: all.
Example: "C:","D:","F:"
.PARAMETER defrag
Defrag disks if warning or critical.
Default: false
.PARAMETER forceDefrag
Defrag disks if free space is low.
Default: false
.EXAMPLE
Only checks all drives with system default warning treshold.
check_diskdefragstatus.ps1
.EXAMPLE
Checks all drives with 15 warning treshold and 40 critical treshold.
check_diskdefragstatus.ps1 -warning 15 -critical 40
.EXAMPLE
Checks only C and D drives with system default warning treshold and 50 critical treshold.
check_diskdefragstatus.ps1 -disks "C:","D:" -critical 50
.EXAMPLE
Checks C drive with system default warning treshold.
If defragmentation status is greater than warning or critical treshold, it runs disk defragmentation.
check_diskdefragstatus.ps1 -disks "C:" -defrag
.EXAMPLE
Checks C drive with system default warning treshold.
If defragmentation status is greater than warning or critical treshold, it runs disk defragmentation even C: disk free space is low.
check_diskdefragstatus.ps1 -disks "C:" -defrag -forceDefrag
.NOTES
Author: Juan Granados
#>
Param(
[Parameter(Mandatory = $false, Position = 0)]
[ValidateRange(0, 100)]
[int]$warning = 0,
[Parameter(Mandatory = $false, Position = 1)]
[ValidateRange(0, 100)]
[int]$critical = 0,
[Parameter(Mandatory = $false, Position = 2)]
[ValidateNotNullOrEmpty()]
[string[]]$disks = "all",
[Parameter()]
[switch]$defrag,
[Parameter()]
[switch]$forceDefrag
)
#Requires -RunAsAdministrator
$ErrorActionPreference = "Stop"
$global:nagiosStatus = 0
$global:nagiosOutput = ""
Function Defrag-Disk($diskToDefrag) {
If ($forceDefrag) {
Write-Verbose "Forcing $($diskToDefrag.DriveLetter) defragmentation"
$result = $diskToDefrag.Defrag($true)
}
Else {
Write-Verbose "Performing $($diskToDefrag.DriveLetter) defragmentation"
$result = $diskToDefrag.Defrag($false)
}
If ($result.ReturnValue -eq 0) {
Write-Verbose "Defragmentation successful"
Write-Verbose "Current fragmentation is $($result.DefragAnalysis.FilePercentFragmentation)"
$diskToDefrag.DefragResult = $result
If (($critical -gt 0) -and ($result.DefragAnalysis.FilePercentFragmentation -gt $critical)) {
Write-Verbose "Status is critical"
$global:nagiosStatus = 2
}
Elseif (($warning -eq 0 -and $result.DefragAnalysis.FilePercentFragmentation -gt 10) -or ( ($warning -gt 0) -and ($result.DefragAnalysis.FilePercentFragmentation -gt $warning))) {
Write-Verbose "Status is warning"
$global:nagiosStatus = 1
}
}
Else {
Write-Output "CRITICAL: Error $($result.ReturnValue) defragmenting drive $($diskToDefrag.DriveLetter)"
Write-Output "Check error codes: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/vdswmi/defrag-method-in-class-win32-volume"
Exit(2)
}
$global:nagiosOutput += "Disk $($diskToDefrag.DriveLetter) fragmentation is $($result.DefragAnalysis.FilePercentFragmentation)."
}
Try {
If ($disks -eq "all") {
$drives = get-wmiobject win32_volume | Where-Object { $_.DriveType -eq 3 -and $_.DriveLetter -and (Get-WMIObject Win32_LogicalDiskToPartition | Select-Object Dependent) -match $_.DriveLetter }
}
Else {
Foreach ($disk in $disks) {
If (-not ($disk -match '[A-Za-z]:')) {
Write-Output "UNKNOWN: Error $($drive) is not a valid disk unit. Expected N:, where N is drive unit. Example C: or D: or F:"
Exit(3)
}
}
$drives = get-wmiobject win32_volume | Where-Object { $_.DriveType -eq 3 -and $_.DriveLetter -in $disks }
}
If (-not ($drives)) {
Write-Output "UNKNOWN: No drives found with get-wmiobject win32_volume command"
Exit(3)
}
Foreach ($drive in $drives) {
Write-Verbose "Analizing drive $($drive.DriveLetter)"
$result = $drive.DefragAnalysis()
If ($result.ReturnValue -eq 0) {
Write-Verbose "Current fragmentation is $($result.DefragAnalysis.FilePercentFragmentation)"
$drive | Add-Member -NotePropertyName 'DefragResult' -NotePropertyValue $result
If (($critical -gt 0) -and ($result.DefragAnalysis.FilePercentFragmentation -gt $critical)) {
If (-not $defrag) {
Write-Verbose "Disk will not be defragmented. Status is critical"
$global:nagiosStatus = 2
}
Else {
Defrag-Disk -diskToDefrag $drive
Continue
}
}
Elseif (($warning -eq 0 -and $result.DefragRecommended -eq "True") -or ( ($warning -gt 0) -and ($result.DefragAnalysis.FilePercentFragmentation -gt $warning))) {
If (-not $defrag) {
Write-Verbose "Disk will not be defragmented. Status is warning"
$global:nagiosStatus = 1
}
Else {
Defrag-Disk -diskToDefrag $drive
Continue
}
}
$global:nagiosOutput += "Disk $($drive.DriveLetter) fragmentation is $($result.DefragAnalysis.FilePercentFragmentation)."
}
Else {
Write-Output "CRITICAL: Error $($result.ReturnValue) checking status of drive $($drive.DriveLetter)"
Write-Output "Check error codes: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/vdswmi/defraganalysis-method-in-class-win32-volume#return-value"
Exit(2)
}
}
}
Catch {
Write-Output "CRITICAL: $($_.Exception.Message)"
Exit(2)
}
$global:nagiosOutput += " |"
If ($critical -eq 0) {
$critical = 50;
}
If ($warning -eq 0) {
$warning = 10;
}
Foreach ($drive in $drives) {
$global:nagiosOutput += " $($drive.DriveLetter.TrimEnd(':'))=$($drive.DefragResult.DefragAnalysis.FilePercentFragmentation)%;$($warning);$($critical);0;100"
}
If ($global:nagiosStatus -eq 2) {
Write-Output "CRITICAL: $($global:nagiosOutput)"
Exit(2)
}
Elseif ($global:nagiosStatus -eq 1) {
Write-Output "WARNING: $($global:nagiosOutput)"
Exit(1)
}
Else {
Write-Output "OK: disk fragmentation is correct.$($global:nagiosOutput)"
Exit(0)
}