Last mod: 2026.04.12
Linux HDD spin down configuration
Instructions for configuring a Linux system to spin down an HDD after a specified period of inactivity. The following description presents one of at least several possible methods for spinning down idle HDD drives. The advantage of this method, however, is that it should work with drives connected not only via SATA but also via USB.
Prerequisites
The instructions have been tested on a Raspberry Pi 4 running Debian GNU/Linux 12 (Bookworm) with a disk connected via USB3.
Install packages:
sudo apt update
sudo apt install -y hdparm sysstat bc
Scripts
disk-monitor.sh
Create file /usr/local/bin/disk-monitor.sh:
vi /usr/local/bin/disk-monitor.sh
with body:
#!/bin/bash
# Script for monitoring disk activity on /dev/sda
# If the disk is idle for 60 seconds, it is put into sleep mode
DISK="/dev/sda"
IDLE_TIMEOUT=3600
LAST_ACTIVITY_FILE="/tmp/disk_activity_timestamp"
CHECK_INTERVAL=5
# Log file
LOG_FILE="/var/log/disk-monitor.log"
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
# Initialization
log_message "Starting disk monitor for $DISK"
while true; do
# Check disk activity using iostat
# Read the number of I/O operations
CURRENT_IO=$(cat /proc/diskstats | grep -w sda | awk '{print $1}')
# If the last activity file does not exist, create it
if [ ! -f "$LAST_ACTIVITY_FILE" ]; then
echo "$(date +%s)" > "$LAST_ACTIVITY_FILE"
log_message "Timestamp file has been created"
fi
# Read the latest timestamp
LAST_TIMESTAMP=$(cat "$LAST_ACTIVITY_FILE")
CURRENT_TIMESTAMP=$(date +%s)
TIME_IDLE=$((CURRENT_TIMESTAMP - LAST_TIMESTAMP))
# Check if the disk is active
# Use iostat to verify actual activity
if command -v iostat &> /dev/null; then
# Check using iostat
IO_PERCENT=$(iostat -x 1 2 | grep sda | tail -1 | awk '{print $4}')
if (( $(echo "$IO_PERCENT > 0" | bc -l) )); then
echo "$(date +%s)" > "$LAST_ACTIVITY_FILE"
log_message "Disk activity detected - IO: $IO_PERCENT%"
fi
else
# Fallback – if iostat is not available, check /proc/diskstats
CURRENT_READS=$(cat /proc/diskstats | grep -w sda | awk '{print $4}')
LAST_READS=$(cat "$LAST_ACTIVITY_FILE.reads" 2>/dev/null || echo "0")
if [ "$CURRENT_READS" != "$LAST_READS" ]; then
echo "$(date +%s)" > "$LAST_ACTIVITY_FILE"
echo "$CURRENT_READS" > "$LAST_ACTIVITY_FILE.reads"
log_message "Disk activity detected - odczyty: $CURRENT_READS"
else
echo "$CURRENT_READS" > "$LAST_ACTIVITY_FILE.reads"
fi
fi
# Updating inactivity timeout
LAST_TIMESTAMP=$(cat "$LAST_ACTIVITY_FILE")
CURRENT_TIMESTAMP=$(date +%s)
TIME_IDLE=$((CURRENT_TIMESTAMP - LAST_TIMESTAMP))
# If the disk is idle for IDLE_TIMEOUT seconds
if [ $TIME_IDLE -ge $IDLE_TIMEOUT ]; then
log_message "Drive idle for $TIME_IDLE seconds – entering sleep mode"
sudo hdparm -Y /dev/sda 2>> "$LOG_FILE"
if [ $? -eq 0 ]; then
log_message "Disk $DISK successfully spun down"
rm -f "$LAST_ACTIVITY_FILE"
else
log_message "ERROR: Failed to spin down disk $DISK"
fi
fi
sleep $CHECK_INTERVAL
done
Two important parameters that must be configured for your disk:
- DISK="/dev/sda" - specify the HDD disk to be checked and stopped
- IDLE_TIMEOUT=3600 - time in seconds after which it will be stopped due to inactivity
Add execution permissions:
sudo chmod +x /usr/local/bin/disk-monitor.sh
disk-monitor.service
Create file disk-monitor.service:
sudo vi /etc/systemd/system/disk-monitor.service
with body:
[Unit]
Description=HDD activity monitor and sleep service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/disk-monitor.sh
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=disk-monitor
TimeoutStopSec=10
[Install]
WantedBy=multi-user.target
Add execution permissions:
sudo chmod 644 /etc/systemd/system/disk-monitor.service
Enable and start the service:
```bash
sudo systemctl daemon-reload
sudo systemctl enable disk-monitor.service
sudo systemctl start disk-monitor.service
Problems
In case of problems, check using the following command whether the disk is stopping programmatically:
sudo hdparm -Y /dev/sda