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