Skip to main content

How to Get the Temperature of a Hard Drive in Batch Script

Heat is the silent killer of hard drives and SSDs. When a drive operates consistently above its thermal threshold, its lifespan decreases dramatically and the risk of sudden failure increases. Monitoring drive temperature is especially critical in servers, NAS enclosures, and laptops with poor ventilation. A Batch script can use PowerShell's Get-StorageReliabilityCounter to pull temperature data from S.M.A.R.T. sensors reported by the drive's firmware.

This guide will explain how to monitor drive temperatures programmatically.

Temperature Safe Ranges

Drive TypeOptimal RangeWarningCritical
HDD (Mechanical)25–45°C46–54°C55°C+ (accelerated wear)
SATA SSD25–50°C51–69°C70°C+ (reduced lifespan)
NVMe SSD25–60°C61–79°C80°C+ (thermal throttling begins)
Sustained High Temperature Is an Emergency

A drive consistently operating above its critical threshold is actively degrading. NVMe SSDs will throttle performance to reduce heat, but HDDs have no such protection: they simply fail faster. If monitoring detects sustained critical temperatures, improve airflow, check fans, or reduce workload immediately.

Method 1: Temperature Report for All Drives

This method reads the temperature of every physical disk using Get-StorageReliabilityCounter and displays it alongside drive identification and a status assessment.

Implementation

@echo off
setlocal

echo [INFO] Reading drive temperatures...
echo --------------------------------------------------

powershell -NoProfile -Command ^
"$disks = Get-PhysicalDisk -ErrorAction SilentlyContinue;" ^
"if (-not $disks) {" ^
" Write-Host 'Get-PhysicalDisk not available on this system.';" ^
" exit 1" ^
"};" ^
"$hasData = $false;" ^
"$results = @();" ^
"foreach ($d in $disks) {" ^
" $counter = $d | Get-StorageReliabilityCounter -ErrorAction SilentlyContinue;" ^
" $temp = $counter.Temperature;" ^
" if ($null -eq $temp -or $temp -eq 0 -or $temp -ge 200) {" ^
" $tempStr = 'N/A';" ^
" $status = '(not reported)'" ^
" } else {" ^
" $hasData = $true;" ^
" $tempStr = \"${temp}C\";" ^
" $mediaType = [string]$d.MediaType;" ^
" $status = switch ($true) {" ^
" ($mediaType -match 'SSD' -and $d.BusType -eq 'NVMe' -and $temp -ge 80) { '[CRITICAL]' }" ^
" ($mediaType -match 'SSD' -and $d.BusType -eq 'NVMe' -and $temp -ge 61) { '[WARNING]' }" ^
" ($mediaType -match 'SSD' -and $d.BusType -ne 'NVMe' -and $temp -ge 70) { '[CRITICAL]' }" ^
" ($mediaType -match 'SSD' -and $d.BusType -ne 'NVMe' -and $temp -ge 51) { '[WARNING]' }" ^
" ($mediaType -match 'HDD' -and $temp -ge 55) { '[CRITICAL]' }" ^
" ($mediaType -match 'HDD' -and $temp -ge 46) { '[WARNING]' }" ^
" ($temp -ge 70) { '[WARNING]' }" ^
" default { '[OK]' }" ^
" }" ^
" };" ^
" $results += [PSCustomObject]@{" ^
" Disk = $d.DeviceId;" ^
" Model = $d.FriendlyName;" ^
" Type = if ($d.BusType -eq 'NVMe') { 'NVMe SSD' }" ^
" elseif ($d.MediaType -match 'SSD') { 'SATA SSD' }" ^
" elseif ($d.MediaType -match 'HDD') { 'HDD' }" ^
" else { [string]$d.MediaType };" ^
" Temp = $tempStr;" ^
" Status = $status" ^
" }" ^
"};" ^
"$results | Format-Table -AutoSize;" ^
"if (-not $hasData) {" ^
" Write-Host '';" ^
" Write-Host 'No temperature data was returned by any drive.';" ^
" Write-Host 'This may be because:';" ^
" Write-Host ' - Drives are connected via USB (bridge chips block S.M.A.R.T.)';" ^
" Write-Host ' - The storage driver does not support reliability counters';" ^
" Write-Host ' - The script is not running as Administrator';" ^
" Write-Host '';" ^
" Write-Host 'Try running as Administrator, or use CrystalDiskInfo for detailed S.M.A.R.T. data.'" ^
"}"

echo --------------------------------------------------

endlocal
exit /b 0

Sample output:

Disk Model Type Temp Status
---- ----- ---- ---- ------
0 Samsung SSD 970 EVO Plus 500GB NVMe SSD 52C [OK]
1 WDC WD40EFAX-68JH4N1 HDD 38C [OK]
2 Kingston DataTraveler 3.0 SATA SSD N/A (not reported)

Why temperature may show "N/A":

  • USB-connected drives: USB bridge chips typically do not pass S.M.A.R.T. data (including temperature) from the drive controller to the operating system.
  • Some SATA SSDs: Not all SSD controllers expose temperature through the Windows storage reliability interface.
  • Not running as Administrator: Get-StorageReliabilityCounter requires elevation on most systems.
  • Virtual machine disks: Virtual disks have no physical temperature sensor.
NVMe Composite Temperature

NVMe SSDs report a "Composite Temperature", a weighted average of multiple internal sensors (controller, flash chips, interface). This single value from Get-StorageReliabilityCounter is the standard monitoring metric. For individual sensor readings, use the NVMe manufacturer's management tool.

Method 2: Overheat Alert Monitor

This method checks all drives against their type-specific thresholds and generates alerts for any drive exceeding safe limits.

@echo off
setlocal

set "LogFile=%~dp0drive_temp.log"

echo [INFO] Checking for overheating drives...

for /f "tokens=1-4 delims=|" %%a in (
'powershell -NoProfile -Command ^
"$alerts = @();" ^
"$disks = Get-PhysicalDisk -ErrorAction SilentlyContinue;" ^
"if (-not $disks) { Write-Output ''NO_DATA|0|0|''; exit 0 };" ^
"$checked = 0; $overheating = 0;" ^
"foreach ($d in $disks) {" ^
" $c = $d | Get-StorageReliabilityCounter -ErrorAction SilentlyContinue;" ^
" if ($null -eq $c.Temperature -or $c.Temperature -eq 0) { continue };" ^
" $checked++;" ^
" $temp = $c.Temperature;" ^
" $isNVMe = $d.BusType -eq ''NVMe'';" ^
" $isSSD = $d.MediaType -match ''SSD'';" ^
" $critical = if ($isNVMe) { 80 } elseif ($isSSD) { 70 } else { 55 };" ^
" $warning = if ($isNVMe) { 61 } elseif ($isSSD) { 51 } else { 46 };" ^
" if ($temp -ge $warning) {" ^
" $overheating++;" ^
" $level = if ($temp -ge $critical) { ''CRITICAL'' } else { ''WARNING'' };" ^
" $alerts += $level`: $($d.FriendlyName) at ${temp}C (threshold: ${warning}C)" ^
" }" ^
"};" ^
"$alertStr = $alerts -join ''|'';" ^
"Write-Output $checked|$overheating|$($disks.Count)|$alertStr;" ^
"if ($overheating -gt 0) { exit 1 } else { exit 0 }"'
) do (
set "Checked=%%a"
set "Overheating=%%b"
set "TotalDisks=%%c"
set "Alerts=%%d"
)

set "PSResult=%errorlevel%"

:: Generate timestamp
for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format ''yyyy-MM-dd HH:mm:ss''"'
) do set "Timestamp=%%t"

if "%Checked%"=="NO_DATA" (
echo [INFO] Could not read temperature data.
endlocal
exit /b 0
)

echo [%Timestamp%] Checked %Checked% of %TotalDisks% disk(s^), %Overheating% overheating.

if %PSResult% equ 0 (
echo [OK] All monitored drives are within safe temperature ranges.
echo [%Timestamp%] OK: All %Checked% monitored drives within limits on %COMPUTERNAME% >> "%LogFile%"
) else (
echo.
echo [ALERT] Overheating drive(s^) detected:

:: Display each alert (pipe-delimited)
powershell -NoProfile -Command "'%Alerts%'.Split('|') | ForEach-Object { Write-Host \" $_\" }"

echo.
echo Recommended actions:
echo - Check case/enclosure airflow and fan operation
echo - Verify the drive is not blocked by cables or other components
echo - Reduce I/O workload if possible
echo - Consider adding case fans or improving ventilation
echo.

echo [%Timestamp%] ALERT: %Overheating% overheating drive(s^) on %COMPUTERNAME% >> "%LogFile%"

:: Write to Event Log
eventcreate /T WARNING /ID 920 /L APPLICATION /SO "DiskTempMonitor" ^
/D "Drive temperature alert on %COMPUTERNAME%: %Overheating% drive(s) exceeding thermal thresholds" >nul 2>&1
)

endlocal
exit /b %PSResult%

Scheduling for continuous monitoring:

Run this as a scheduled task every 30 minutes during business hours. The exit code (0 = OK, 1 = alert) integrates with Task Scheduler's failure actions or monitoring tools.

When to Check More Frequently

During heat waves, heavy workloads (database maintenance, backup runs, video rendering), or after hardware changes (adding a new drive, moving a server), increase the check frequency to every 10–15 minutes until you've confirmed temperatures are stable.

Method 3: Temperature Trend Logger

Single readings can be misleading: a drive may spike during a backup but cool down quickly. Trend logging reveals the pattern: is the drive consistently warm, getting warmer over time, or just spiking during specific operations?

@echo off
setlocal

set "LogFile=%~dp0temp_history_%COMPUTERNAME%.csv"
set "Interval=300"

if not exist "%LogFile%" (
echo "Timestamp","Disk","Model","Type","TempC" > "%LogFile%"
)

title Drive Temperature Logger - Every %Interval%s

echo [INFO] Logging drive temperatures every %Interval% seconds.
echo [INFO] Log file: %LogFile%
echo [INFO] Press Ctrl+C to stop.
echo --------------------------------------------------

:TempLoop
powershell -NoProfile -Command ^
"$ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss';" ^
"$disks = Get-PhysicalDisk -ErrorAction SilentlyContinue;" ^
"if (-not $disks) { exit 0 };" ^
"foreach ($d in $disks) {" ^
" $c = $d | Get-StorageReliabilityCounter -ErrorAction SilentlyContinue;" ^
" if ($null -ne $c.Temperature -and $c.Temperature -gt 0) {" ^
" $type = if ($d.BusType -eq 'NVMe') { 'NVMe' } elseif ($d.MediaType -match 'SSD') { 'SATA_SSD' } else { 'HDD' };" ^
" $line = '\"' + $ts + '\",\"' + $d.DeviceId + '\",\"' + $d.FriendlyName + '\",\"' + $type + '\",\"' + $c.Temperature + '\"';" ^
" Add-Content -Path '%LogFile%' -Value $line;" ^
" Write-Host \" [$ts] Disk $($d.DeviceId): $($c.Temperature)C ($type)\"" ^
" }" ^
"}"

timeout /t %Interval% >nul
goto :TempLoop

How to analyze the trend data:

  1. Open the CSV in Excel.
  2. Create a line chart with Timestamp on the X-axis and TempC on the Y-axis, grouped by Disk.
  3. Look for these patterns:
PatternMeaningAction
Flat line at 30–40°CNormal, stable operationNo action needed
Gradual upward trend over daysDust accumulation, fan degradation, or increasing workloadClean fans, check airflow
Sharp spikes that return to baselineTemporary heavy I/O (backup, defrag, large copy)Normal, verify the spike doesn't hit critical thresholds
Permanently elevated after a changeNew component blocking airflow, or new workloadInvestigate the change; improve cooling
Approaching critical threshold consistentlyImminent thermal damage riskImprove cooling urgently or reduce workload

Method 4: Fleet-Wide Temperature CSV

For monitoring temperatures across multiple servers or workstations.

@echo off
setlocal

set "CSVFile=\\Server\Audit\drive_temperatures.csv"

if not exist "%CSVFile%" (
echo "Timestamp","Computer","Disk","Model","Type","TempC","Health" > "%CSVFile%" 2>nul
)

powershell -NoProfile -Command ^
"$ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss';" ^
"$disks = Get-PhysicalDisk -ErrorAction SilentlyContinue;" ^
"if (-not $disks) { exit 0 };" ^
"foreach ($d in $disks) {" ^
" $c = $d | Get-StorageReliabilityCounter -ErrorAction SilentlyContinue;" ^
" $temp = if ($null -ne $c.Temperature -and $c.Temperature -gt 0) { $c.Temperature } else { 'N/A' };" ^
" $type = if ($d.BusType -eq 'NVMe') { 'NVMe' } elseif ($d.MediaType -match 'SSD') { 'SATA_SSD' } else { 'HDD' };" ^
" Write-Output ('\"' + $ts + '\",\"' + $env:COMPUTERNAME + '\",\"' + $d.DeviceId + '\",\"' + $d.FriendlyName + '\",\"' + $type + '\",\"' + $temp + '\",\"' + $d.HealthStatus + '\"')" ^
"}" >> "%CSVFile%" 2>nul

echo [OK] Temperature data exported for %COMPUTERNAME%.

endlocal
exit /b 0

What to look for in the fleet CSV:

  • Temperatures above type-specific thresholds: Sort by TempC descending to find the hottest drives.
  • Servers with multiple hot drives: May indicate a chassis cooling problem (failed fan, blocked vent, ambient temperature issue) rather than an individual drive problem.
  • Temperature differences between identical servers: If two servers with the same hardware show different temperatures, investigate the hotter one's physical environment.

How to Avoid Common Errors

Problem: Temperature Shows 0 or N/A

Not all drives report temperature through Get-StorageReliabilityCounter. Common causes:

  • USB-connected drives: USB bridge chips typically block S.M.A.R.T. passthrough.
  • Some SATA SSDs: Not all controllers expose temperature via the Windows storage interface.
  • Not running as Administrator: Reliability counters require elevation on most systems.
  • Virtual machine disks: No physical temperature sensor exists.

Solution: For drives that don't report via Get-StorageReliabilityCounter, use third-party tools like CrystalDiskInfo or smartctl (from smartmontools), which can access S.M.A.R.T. data directly through the drive controller.

Problem: NVMe Composite Temperature vs. Individual Sensors

NVMe SSDs have multiple internal sensors (controller, flash chips, interface). Get-StorageReliabilityCounter returns the "Composite Temperature", a weighted average. The controller sensor may be significantly hotter than the composite reading.

Solution: For detailed per-sensor NVMe temperature, use the manufacturer's management tool (Samsung Magician, Intel SSD Toolbox, etc.) or smartctl -a /dev/sdX on Linux. The composite temperature from Method 1 is sufficient for general monitoring and alerting.

Problem: Temperature Readings Seem Too Low

If a drive reports 0°C or a suspiciously low value, the S.M.A.R.T. data may be returning raw values in a format the Windows storage interface doesn't interpret correctly.

Solution: Cross-reference with CrystalDiskInfo or the manufacturer's diagnostic tool. If a discrepancy exists, rely on the third-party tool for accurate readings.

Best Practices and Rules

1. Know Your Thresholds by Drive Type

NVMe SSDs tolerate higher temperatures than SATA SSDs, which tolerate higher temperatures than HDDs. Apply the correct thresholds for each drive type (see the table at the top).

A single reading of 42°C is meaningless without context. Use Method 3 to log temperatures over time and identify whether temperatures are stable, rising, or spiking.

3. Check After Physical Changes

After adding a new drive, moving a server, or changing the case configuration, monitor temperatures closely for 24–48 hours. New components can block airflow to existing drives.

4. Correlate Temperature with Health Status

A drive that is both hot AND showing "Warning" health status is in critical condition. Method 4's CSV includes both temperature and health status for correlation.

5. Run Checks as Administrator

Get-StorageReliabilityCounter requires elevation on most systems. Running without admin rights returns no data, which the script reports as "N/A", potentially masking a temperature problem.

6. Consider Physical Environment

Drive temperatures are affected by ambient room temperature, case airflow, fan speed, drive bay density, and workload intensity. A drive running at 50°C in a 30°C server room may be normal; the same temperature in a 20°C air-conditioned room suggests a cooling problem.

Conclusions

Monitoring drive temperature provides early warning of thermal conditions that accelerate hardware failure. By using Get-StorageReliabilityCounter for type-aware temperature reading, applying drive-type-specific thresholds, logging trends over time, and alerting on threshold violations, you catch cooling problems before they cause data loss. This proactive monitoring is essential for servers, NAS devices, and any environment where drives operate under sustained load or in warm conditions.