← Files

sata-spindown-guard 🌓🛡️#

A safe, cron-friendly guard script that automatically spins down idle SATA HDDs and prevents them from being left spinning when not in use.

sata-spindown-guard.sh is a robust, production-ready Bash utility that monitors one or more SATA hard drives and powers them down when they are not mounted and remain in the active/idle state for too long.
It is designed to run periodically from cron as a safety layer on top of your backup or archive workflows, ensuring that cold-storage disks are not wasting power or wearing out their mechanics.


⚡ Quick Start#

Yes, both will be executable.
The install chain handles it automatically:


Installation#

# Clone the repository
git clone https://github.com/paulmann/sata-spindown-guard.git
cd sata-spindown-guard

# Install globally as `hddown` — resolves absolute path, ensures executable bit, creates symlink
clear && \
src="$(readlink -f ./sata-spindown-guard.sh 2>/dev/null \
  || realpath ./sata-spindown-guard.sh 2>/dev/null \
  || echo "")" \
  && [ -n "$src" ] \
  && [ -f "$src" ] \
  && { [ -x "$src" ] || chmod +x "$src"; } \
  && sudo ln -sf "$src" /usr/local/bin/hddown \
  && sudo ln -sf "$src" /usr/local/bin/hddoff \
  && sudo ln -sf "$src" /usr/local/bin/hdd_poweroff_guard.sh \
  && sudo ln -sf "$src" /usr/local/bin/hdd_poweroff_guard \
  ; echo "" \
  ; echo "" \
  ; echo "✅ Installed successfully!" \
  ; echo "   Commands: hddown, hddoff, hdd_poweroff_guard" \
  ; echo "✅ Installed successfully!" \
  ; echo "   Source:  $src" \
  ; echo "" \
  ; ls -la /usr/local/bin/hddown \
            /usr/local/bin/hddoff \
            /usr/local/bin/hdd_poweroff_guard \
            /usr/local/bin/hdd_poweroff_guard.sh 2>/dev/null

The install command automatically resolves the absolute path, grants the executable
bit to the source script if missing, and creates the /usr/local/bin/hddown symlink.
Since a symlink inherits permissions from its target, both sata-spindown-guard.sh
and hddown will be executable upon completion.


Verify Installation#

which hddown
# → /usr/local/bin/hddown

ls -la "$(which hddown)"
# → lrwxrwxrwx ... /usr/local/bin/hddown -> /path/to/sata-spindown-guard.sh

Usage#

Below are typical usage patterns for a single backup disk /dev/sda that is mounted at /mnt/backup only during actual backups.

# Show help and list all ATA disks discovered in /dev/disk/by-id/
hddown --help

# Power off a single SATA HDD by device name (auto-resolves /dev/disk/by-id/)
hddown -s sda

# Power off multiple disks explicitly by by-id names
hddown -i ata-WDC_WD10EZEX-00BBHA0_WD-WCC6Y0SLCEHT \
       -i ata-ST4000DM004-2CV104_ZFNXXXXXX

# Dry run — simulate actions without touching drive power state
hddown -s sda --dry-run

# Wake up a sleeping/standby drive (spin it up via minimal read I/O)
hddown -w -s sda

# Process disks from environment variables instead of CLI arguments
HDD_ID=ata-WDC_WD10EZEX-00BBHA0_WD-WCC6Y0SLCEHT hddown
HDD_IDS="ata-DISK1_XXX ata-DISK2_YYY" hddown

Typical cron integration#

The script is designed for guard-style cron execution – it checks drive state and powers off only when it is safe to do so.

# Edit root's crontab
sudo crontab -e

Example schedule (every 5 minutes, from 07:30 to 02:00, spanning midnight):

# sata-spindown-guard — protect /dev/sda (backup disk) from being left spinning
30-59/5  7     * * *  /usr/local/bin/hddown -s sda
*/5      8-23  * * *  /usr/local/bin/hddown -s sda
*/5      0-1   * * *  /usr/local/bin/hddown -s sda

Uninstall#

sudo rm /usr/local/bin/hddown && echo "✅ hddown removed from PATH"

📋 Table of Contents#


🚨 Why sata-spindown-guard?#

SATA HDDs used for cold storage, backups, or archives often get mounted periodically, used briefly, and then unintentionally left spinning for hours.
This wastes power, generates unnecessary heat, and accelerates wear on mechanical components.

sata-spindown-guard.sh acts as a stateless safety supervisor: it does not manage your backup jobs, but it ensures that any unmounted drive will be cleanly powered down once it is no longer needed.


How It Works#

At a high level, each run of the script:

  1. Resolves the target disk(s) either from:

    • -s / --dev (e.g. sda) → looks up matching /dev/disk/by-id/ata-*

    • -i / --disk (full by-id name)

    • HDD_ID / HDD_IDS environment variables

  2. Verifies that the disk is an ATA/SATA device (hdparm -i).

  3. Checks that the disk is not mounted, using both:

    • findmnt --source /dev/sdX

    • A configurable safety mount point HDD_MOUNT (e.g. /mnt/backup)

  4. Queries the drive power state via hdparm -C:

    • Handles active, idle, active/idle, standby, sleep, unknown.

  5. If the drive is spinning (active/idle), it:

    • Attempts hdparm -Y (deep sleep), falling back to hdparm -y (standby).

    • If hdparm fails or the firmware does not support ATA power management:

      • Runs a diagnostic path that logs capabilities and
        attempts a forced power-off via:

        • udisksctl power-off -b /dev/sdX (if available), or

        • sysfs SCSI offline + delete as a last resort.

  6. Emits a detailed, timestamped log with safe exit codes suitable for monitoring.

When run with -w / --wake, the script instead issues a minimal dd read to spin the disk up and confirm that it is in active/idle state again.


✨ Key Features#


🛡️ Safety Guarantees#

sata-spindown-guard.sh is built with safety as the first-class concern:


🔧 Installation & Configuration#

System Requirements#

Configuration Options#

All options can be set via environment variables or CLI flags.

Command Line Options#

Usage: hddown [OPTIONS]

  -h, --help            Show help and list available ATA disks
  -v, --version         Show version information
  -d, --dry-run         Simulate without making any changes to the drive
  -w, --wake            Wake mode: spin up drives from standby/sleep
  -s, --dev DEV         Device name (e.g. sda) — disk ID resolved automatically
  -i, --disk ID         Disk ID from /dev/disk/by-id/ (can be repeated)

Usage Examples#

# Simple: guard a single backup disk
hddown -s sda

# Guard multiple named disks from cron
hddown -i ata-DISK1_XXX -i ata-DISK2_YYY

# Increase hdparm timeout for slow/large disks
TIMEOUT_SEC=30 hddown -s sda

# Use a custom log file location
LOG_FILE=/var/log/sata-spindown-guard.log hddown -s sda

# Fully simulated run with verbose logging (run manually)
DRY_RUN=true hddown -s sda

📊 Logging & Monitoring#

The script writes a structured log with timestamps and levels:

[2026-03-15 19:13:42] [INFO]    [sata-spindown-guard.sh] Disk is not mounted — safe to proceed
[2026-03-15 19:13:42] [INFO]    [sata-spindown-guard.sh] Drive state: active/idle
[2026-03-15 19:13:42] [SUCCESS] [sata-spindown-guard.sh] Drive powered down successfully (state: standby)

You can hook this into Prometheus exporters, Nagios, Zabbix, or any log-based alerting system.


🔍 Troubleshooting#

Drive always reported as active/idle#

Power-off not supported by firmware#

When hdparm -Y/-y fail, the script:

Permission errors#

Always run from root or via sudo when touching block devices:

sudo hddown -s sda

🤝 Contributing#

Contributions, feature requests, and bug reports are very welcome.

Development Setup#

git clone https://github.com/paulmann/sata-spindown-guard.git
cd sata-spindown-guard

# Basic syntax check
bash -n sata-spindown-guard.sh

# Dry-run on a test system
DRY_RUN=true ./sata-spindown-guard.sh -s sda

Contribution Guidelines#

  1. Fork the repository.

  2. Create a feature branch: git checkout -b feature/your-feature.

  3. Test your changes thoroughly on a non-production system.

  4. Commit with a clear message: git commit -m 'Add XYZ feature'.

  5. Push to your fork: git push origin feature/your-feature.

  6. Open a Pull Request describing your changes and rationale.

Code Standards#


📄 License#

This project is licensed under the PolyForm Noncommercial License 1.0.0 – see the LICENSE file for details.


👨‍💻 Author & Support#

Mikhail Deynekin

Getting Help#


⭐ Star this repository if it helps you!#

sata-spindown-guard – Keeping your backup drives truly cold when they should rest. 🌓🛡️