When working with storage automation scripts, many developers face a frustrating paradox: standard tools like hdparm -C
and smartctl -i
actually wake sleeping drives during status checks. This defeats the purpose of power management scripts that aim to maintain drives in low-power states.
Consider a scenario where you're managing a NAS with multiple drives that should sleep during low-usage periods. Traditional monitoring approaches create a vicious cycle:
# Bad example - this wakes the drive
hdparm -C /dev/sdb
Each status check becomes a power state interruption, potentially reducing drive lifespan and increasing energy costs.
Here are several methods to determine drive state without causing wake-ups:
1. Using sysfs Interface
Linux exposes drive state information through sysfs. This method is read-only and shouldn't trigger drive activation:
cat /sys/block/sdX/device/state
Possible outputs include "active", "standby", or "sleeping". The advantage is zero drive interaction - it simply reads cached state information.
2. Monitoring Disk Activity
Combine sysfs with disk statistics to infer power state:
# Check if sector count changes over time
sectors1=$(cat /sys/block/sdX/stat | awk '{print $3}')
sleep 10
sectors2=$(cat /sys/block/sdX/stat | awk '{print $3}')
if [ "$sectors1" -eq "$sectors2" ]; then
echo "Drive likely in standby"
fi
3. Using udisks2 (DBus Interface)
For systems with udisks2, this provides a cleaner API:
dbus-send --system --print-reply \
--dest=org.freedesktop.UDisks2 \
/org/freedesktop/UDisks2/block_devices/sdb \
org.freedesktop.DBus.Properties.Get \
string:org.freedesktop.UDisks2.Drive string:Configuration
Here's a complete bash script that safely monitors drive states:
#!/bin/bash
DRIVE="/dev/sdb"
SYSFS_PATH="/sys/block/${DRIVE##*/}/device/state"
get_drive_state() {
# Use sysfs to get current state
state=$(cat "$SYSFS_PATH" 2>/dev/null)
# Fallback to smartctl if sysfs unavailable
if [ -z "$state" ]; then
state=$(smartctl -i "$DRIVE" | grep -i "power mode" | awk '{print $NF}')
# Note: This may wake the drive!
fi
echo "$state"
}
current_state=$(get_drive_state)
case "$current_state" in
*standby*|*sleeping*)
echo "Drive is in low-power state"
;;
*active*)
echo "Drive is active"
;;
*)
echo "Unknown state: $current_state"
;;
esac
Remember these important considerations:
- Different drive models may report states differently
- SATA drives generally provide better status visibility than USB
- Consider adding delay between checks to prevent unnecessary polling
- Test thoroughly with your specific hardware configuration
For mission-critical systems, consider writing a custom kernel module that:
- Hooks into the storage subsystem
- Caches drive states
- Provides a procfs or sysfs interface for queries
This avoids userspace tools altogether and provides the most reliable monitoring.
Many system administrators and developers need to monitor drive power states for power management scripts, but standard tools like hdparm -C
and smartctl -i
have an annoying side effect - they wake sleeping drives during the check. This defeats the purpose of power management scripts that aim to keep drives asleep when not in use.
After extensive testing, I've found several methods that can determine drive state without causing wake-ups:
1. Using sysfs
The Linux kernel exposes drive state information through sysfs. Check the /sys/block/sdX/device/state
file:
cat /sys/block/sda/device/state
This typically returns "active" or "standby" without waking the drive.
2. SMART Status via smartmontools
Use smartctl with the -n
(never sleep) flag:
smartctl -n standby /dev/sda
This returns "STANDBY" for sleeping drives without waking them.
Here's a bash function I use in my power management scripts:
function is_drive_sleeping() {
local drive=$1
# Try sysfs first
if [[ -f "/sys/block/${drive}/device/state" ]]; then
state=$(cat "/sys/block/${drive}/device/state")
[[ "$state" == "standby" ]] && return 0
fi
# Fall back to smartctl
smartctl -n standby "/dev/${drive}" | grep -q "STANDBY" && return 0
return 1
}
Here's a complete script that checks drive state and puts it to sleep if needed:
#!/bin/bash
DRIVE="sda"
if is_drive_sleeping "$DRIVE"; then
echo "Drive $DRIVE is already sleeping"
else
echo "Putting drive $DRIVE to sleep"
hdparm -Y "/dev/$DRIVE"
fi
1. Some older drives may still wake up during checks
2. sysfs method works best with modern kernels (4.15+)
3. Always test with your specific hardware configuration