Last mod: 2026.03.07

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

# Skrypt do monitorowania aktywności dysku /dev/sda
# Jeśli dysk jest nieużywany przez 60 sekund, wyłącza go do stanu uśpienia

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"
}

# Inicjalizacja
log_message "Uruchamianie monitora dysku dla $DISK"

while true; do
    # Sprawdzenie aktualności dysku poprzez iostat
    # Odczytujemy liczbę operacji I/O
    CURRENT_IO=$(cat /proc/diskstats | grep -w sda | awk '{print $1}')
    
    # Jeśli plik z ostatnią aktywnością nie istnieje, go tworzymy
    if [ ! -f "$LAST_ACTIVITY_FILE" ]; then
        echo "$(date +%s)" > "$LAST_ACTIVITY_FILE"
        log_message "Utworzono plik timestamp"
    fi
    
    # Odczytujemy ostatni timestamp
    LAST_TIMESTAMP=$(cat "$LAST_ACTIVITY_FILE")
    CURRENT_TIMESTAMP=$(date +%s)
    TIME_IDLE=$((CURRENT_TIMESTAMP - LAST_TIMESTAMP))
    
    # Sprawdzamy czy dysk ma aktywność
    # Używamy iostat do sprawdzenia rzeczywistej aktywności
    if command -v iostat &> /dev/null; then
        # Sprawdzenie przy użyciu 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 "Aktywność dysku wykryta - IO: $IO_PERCENT%"
        fi
    else
        # Fallback - jeśli iostat nie dostępny, sprawdzamy /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 "Aktywność dysku wykryta - odczyty: $CURRENT_READS"
        else
            echo "$CURRENT_READS" > "$LAST_ACTIVITY_FILE.reads"
        fi
    fi
    
    # Aktualizujemy czas bezczynności
    LAST_TIMESTAMP=$(cat "$LAST_ACTIVITY_FILE")
    CURRENT_TIMESTAMP=$(date +%s)
    TIME_IDLE=$((CURRENT_TIMESTAMP - LAST_TIMESTAMP))
    
    # Jeśli dysk jest nieaktywny przez IDLE_TIMEOUT sekund
    if [ $TIME_IDLE -ge $IDLE_TIMEOUT ]; then
        log_message "Dysk nieaktywny przez $TIME_IDLE sekund - wysyłanie do stanu uśpienia"
        sudo hdparm -Y /dev/sda 2>> "$LOG_FILE"
        
        if [ $? -eq 0 ]; then
            log_message "Dysk $DISK pomyślnie uśpiony"
            rm -f "$LAST_ACTIVITY_FILE"
        else
            log_message "BŁĄD: Nie udało się uśpić dysku $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