Skip to content

Instantly share code, notes, and snippets.

@schakko
Last active July 10, 2024 09:37
Show Gist options
  • Save schakko/4713248 to your computer and use it in GitHub Desktop.
Save schakko/4713248 to your computer and use it in GitHub Desktop.
A simple PowerShell script for retrieving the RAID status of volumes with help of diskpart. The nicer solution would be using WMI (which does not contain the RAID status in the Status field of Win32_DiskDrive, Win32_LogicalDisk or Win32_Volume for unknown reason) or using the new PowerShell API introduced with Windows 8 (wrong target system as o…
# A simple PowerShell script for retrieving the RAID status of volumes with help of diskpart.
# The nicer solution would be using WMI (which does not contain the RAID status in the Status field of Win32_DiskDrive, Win32_LogicalDisk or Win32_Volume for unknown reason)
# or using the new PowerShell API introduced with Windows 8 (wrong target system as our customer uses a Windows 7 architecture).
#
# diskpart requires administrative privileges so this script must be executed under an administrative account if it is executed standalone.
# check_mk has this privileges and therefore this script must only be copied to your check_mk/plugins directory and you are done.
#
# Christopher Klein <ckl[at]neos-it[dot]de>
# This script is distributed under the GPL v2 license.
$dp = "list volume" | diskpart | ? { $_ -match "^ [^-]" }
echo `<`<`<local`>`>`>
foreach ($row in $dp) {
# skip first line
if (!$row.Contains("Volume ###")) {
# best match RegExp from http://www.eventlogblog.com/blog/2012/02/how-to-make-the-windows-softwa.html
if ($row -match "\s\s(Volume\s\d)\s+([A-Z])\s+(.*)\s\s(NTFS|FAT)\s+(Mirror|RAID-5|Stripe|Spiegel|Spiegelung|Übergreifend|Spanned)\s+(\d+)\s+(..)\s\s([A-Za-z]*\s?[A-Za-z]*)(\s\s)*.*") {
$disk = $matches[2]
# 0 = OK, 1 = WARNING, 2 = CRITICAL
$statusCode = 1
$status = "WARNING"
$text = "Could not parse line: $row"
$line = $row
if ($line -match "Fehlerfre |OK|Healthy") {
$statusText = "is healthy"
$statusCode = 0
$status = "OK"
}
elseif ($line -match "Rebuild") {
$statusText = "is rebuilding"
$statusCode = 1
}
elseif ($line -match "Failed|At Risk|Fehlerhaf") {
$statusText = "failed"
$statusCode = 2
$status = "CRITICAL"
}
echo "$statusCode microsoft_software_raid - $status - Software RAID on disk ${disk}:\ $statusText"
}
}
}
@LionRelaxe
Copy link

Thanks!
It works fine.
However, I also have the desire to monitor Physical disks, and to report the info trough email....
Here's my modified version (please, be kind... it's my first time ever with PS script).
Note that I pipe DiskPart for disk status instead of "Get-Physicaldisk". I currently have a drive in error, Diskpart flags it, Get-Physicaldisk doesn't.

# A simple PowerShell script for retrieving the RAID status of volumes with help of diskpart.
# The nicer solution would be using WMI (which does not contain the RAID status in the Status field of Win32_DiskDrive, Win32_LogicalDisk or Win32_Volume for unknown reason)
# or using the new PowerShell API introduced with Windows 8 (wrong target system as our customer uses a Windows 7 architecture).
# 
# diskpart requires administrative privileges so this script must be executed under an administrative account if it is executed standalone.
# check_mk has this privileges and therefore this script must only be copied to your check_mk/plugins directory and you are done.
#
# Christopher Klein <ckl[at]neos-it[dot]de>
# This script is distributed under the GPL v2 license.

#Volumes:
$dpV = "list volume" | diskpart | ? { $_ -match "^  [^-]" }
foreach ($row in $dpV) {
	$OutString = $OutString+$row+"`r`n"
	# skip first line
	if (!$row.Contains("Volume ###")) {
		# best match RegExp from http://www.eventlogblog.com/blog/2012/02/how-to-make-the-windows-softwa.html
		if ($row -match "\s\s(Volume\s\d)\s+([A-Z])\s+(.*)\s\s(NTFS|FAT)\s+(Mirror|RAID-5|Stripe|Spiegel|Spiegelung|Übergreifend|Spanned)\s+(\d+)\s+(..)\s\s([A-Za-z]*\s?[A-Za-z]*)(\s\s)*.*")  {
			$disk = $matches[2] 
			# 0 = OK, 1 = WARNING, 2 = CRITICAL
			$statusCode = 1
			$status = "WARNING"
			$text = "Could not parse line: $row"
			$line = $row
			
			if ($line -match "Fehlerfre |OK|Healthy") {
				$statusText = "is healthy"
				$statusCode = 0
				$status = "OK"
			}
			elseif ($line -match "Rebuild") {
				$statusText = "is rebuilding"
				$statusCode = 1
				$VolumeErrorFound = 1
			}
			elseif ($line -match "Failed|At Risk|Fehlerhaf") {
				$statusText = "failed"
				$statusCode = 2
				$status = "CRITICAL"
				$VolumeErrorFound = 1
			}
		
			#echo "$statusCode microsoft_software_raid - $status - Software RAID on disk ${disk}:\ $statusText"
		}
	}
}
$OutString = $OutString+"`r`n"

#Disk:
$dpD = "list disk" | diskpart | ? { $_ -match "^  [^-]" }
foreach ($row in $dpD) {
	# skip first line
	if (!$row.Contains("Volume ###")) {
		$OutString = $OutString+$row+"`r`n"
		# best match RegExp from http://www.eventlogblog.com/blog/2012/02/how-to-make-the-windows-softwa.html
		if ($row -match "Errors") {
			#echo "$row"
			$DiskErrorFound = 1
		}
	}
}
if (($DiskErrorFound) -Or ($VolumeErrorFound)) {
	$SMTPServer = "your.smtp.server"
	$SMTPPort = 25
	$EmailTo = "ENTERYOUR@EMAIL.HERE"
	$EmailFrom = "ENTERYOUR@EMAIL.HERE"
	$EmailSubject = "Disk or Volume Error on $env:computername"
	$EmailBody = $OutString
	Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $EmailSubject -Body $EmailBody -SmtpServer $SMTPServer -Port $SMTPPort
}

@countingpine
Copy link

Hi. There's an issue processing volumes that are "Healthy" but "At Risk".

Here's some real-world data:
Disk Management 2003 Health (At Risk)

DISKPART> list disk

  Disk ###  Status      Size     Free     Dyn  Gpt
  --------  ----------  -------  -------  ---  ---
  Disk 0    Errors       932 GB   301 MB   *
  Disk 1    Online       932 GB   301 MB   *

DISKPART> list volume

  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
  ----------  ---  -----------  -----  ----------  -------  ---------  --------
  Volume 0     E   Data         NTFS   Mirror       831 GB  Healthy    At Risk
  Volume 1                      RAW    Mirror       180 MB  Healthy    At Risk
  Volume 2     C   System       NTFS   Mirror       100 GB  Healthy    At Risk
  Volume 3     D                       DVD-ROM         0 B  Healthy

(Volumes 0-2 are mirrored across Disk 0 and 1, and Disk 0 has errors.)
The volumes are At Risk, but still apparently Healthy. But because the script checks for "Healthy" first, it doesn't spot that they're "At Risk".

I think the checks should be reordered from most to least severe:

		if ($line -match "Failed|At Risk|Fehlerhaf|Data Incomplete|Stale Data|Failed Redundancy|Unknown") {
			$statusText = "failed"
			$statusCode = 2
			$status = "CRITICAL"
			$VolumeErrorFound = 1
		}
		elseif ($line -match "Rebuild|Regenerating|Resynching|Data Not Redundant") {
			$statusText = "is rebuilding"
			$statusCode = 1
			$VolumeErrorFound = 1
		}
		elseif ($line -match "Fehlerfre |OK|Healthy") {
			$statusText = "is healthy"
			$statusCode = 0
			$status = "OK"
		}

I've also added some other possible status values based on https://www.prajwaldesai.com/hard-disk-volume-status/ (possibly taken from https://books.google.co.uk/books?id=RPbQswG_i2EC&pg=PA196)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment