How to Programmatically Detect Windows Safe Mode Status for Nagios Monitoring


7 views

Windows servers occasionally booting into Safe Mode after updates is more common than many admins realize. The real challenge comes when these boots happen silently without obvious visual indicators, especially on headless servers. Here's how to definitively check Safe Mode status through multiple technical approaches.

The most reliable way involves querying the boot configuration data store:

@echo off
reg query "HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Option" /v OptionValue | find "0x1"
if %errorlevel%==0 (
    echo Windows is in Safe Mode
) else (
    echo Windows is in normal mode
)

For more modern systems, this PowerShell snippet provides better integration:

function Test-SafeMode {
    $safeBoot = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option" -Name OptionValue -ErrorAction SilentlyContinue
    if ($safeBoot.OptionValue -eq 1) {
        return $true
    }
    return $false
}

if (Test-SafeMode) {
    Write-Host "System is in Safe Mode"
} else {
    Write-Host "System is in normal operation"
}

For environments where registry access is restricted, WMI provides an alternative:

$bootMode = (Get-WmiObject -Class Win32_ComputerSystem).BootupState
if ($bootMode -match "Safe") {
    # Safe mode detected
}

Here's a complete Nagios plugin example in PowerShell that returns proper exit codes:

param(
    [switch]$verbose
)

$state = 0
$message = "OK: System running in normal mode"

try {
    $safeBoot = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option" -Name OptionValue -ErrorAction Stop
    if ($safeBoot.OptionValue -eq 1) {
        $state = 2
        $message = "CRITICAL: System running in Safe Mode"
    }
} catch {
    $state = 3
    $message = "UNKNOWN: Could not determine boot state"
}

if ($verbose) {
    Write-Host $message
}
exit $state

For absolute certainty, you can cross-validate with these additional checks:

  • Check for missing network adapters (Safe Mode with Networking is different)
  • Verify reduced driver load count through Win32_SystemDriver WMI class
  • Monitor for absent startup programs in HKCU\Software\Microsoft\Windows\CurrentVersion\Run

Some special considerations worth noting:

# Detect Safe Mode with Networking
$netSafe = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Network" -Name "(Default)" -ErrorAction SilentlyContinue
if ($netSafe -and $netSafe."(Default)" -eq "Minimal") {
    Write-Host "Safe Mode with Networking detected"
}

When implementing these checks in production:

  • Cache results for scripts that check frequently
  • Prefer WMI over registry queries in domain environments
  • Handle 32/64-bit registry redirection properly
  • Consider implementing as a Windows service for constant monitoring

The most straightforward method is using the System Configuration utility (msconfig) via command line:

systeminfo | find "Boot Mode"

This will return either "Normal boot" or "Safe boot" in the output. For scripting purposes, you can capture this output programmatically.

Windows stores Safe Mode status in the registry. Here's a PowerShell snippet to check it:

$safeMode = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option").OptionValue
if ($safeMode -eq 1) {
    Write-Host "Running in Safe Mode"
} else {
    Write-Host "Running in Normal Mode"
}

For enterprise environments, WMI provides another reliable method:

wmic OS GET BootOption

Possible return values include:

  • 0 - Normal boot
  • 1 - Fail-safe boot
  • 2 - Fail-safe with network boot

Here's a complete PowerShell script for Nagios passive checks:

# Check Safe Mode status
$isSafeMode = $false
try {
    $bootMode = (Get-WmiObject -Class Win32_OperatingSystem).BootOption
    if ($bootMode -eq 1 -or $bootMode -eq 2) {
        $isSafeMode = $true
    }
} catch {
    # Fallback to registry method
    try {
        $safeModeValue = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option" -ErrorAction Stop).OptionValue
        if ($safeModeValue -eq 1) {
            $isSafeMode = $true
        }
    } catch {
        Write-Host "UNKNOWN: Could not determine boot mode"
        exit 3
    }
}

# Prepare Nagios output
if ($isSafeMode) {
    Write-Host "CRITICAL: Server is running in Safe Mode"
    exit 2
} else {
    Write-Host "OK: Server is running in Normal Mode"
    exit 0
}

For older Windows versions, you might need to check environment variables:

echo %SAFEBOOT_OPTION%

Or examine the boot.ini file (pre-Windows Vista):

find /i "/safeboot" %systemroot%\boot.ini

When implementing automated checks:

  • Schedule checks to run shortly after system startup
  • Implement multiple verification methods for redundancy
  • Log all mode changes for troubleshooting
  • Consider checking HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Minimal and Network keys for specific safe mode types