Safe to manually spin down hard drive with hdparm?

21,699

Solution 1

Instead of manually trying to figure this out, rely on existing stuff. I use hd-idle on my file server, it works great. I also don’t unmount my drives because there’s really no reason to do so. If I want to access a file, the disks will spin up. Then, after the timeout passes, they’ll spin down again.

If you’re super paranoid about data integrity, you can use autofs, which can automatically mount and umount your filesystems on an as-needed basis. I haven’t used it myself, but the ArchWiki page offers some info that looks quite usable.

Solution 2

Note

You don't need to umount the partitions in order to spin down the hard drive. It will be easier if you just set a standby timeout (that will trigger after some time not being used). This way, when needed, the disk will awake (spin-up) and you'll be able to use it straight away without the need to remount the partitions.

Command-line solution

As @Nattgew has suggested on a comment, use hdparm (if that's the tool you like to use) with the -S option to set a standby timeout:

-S   Set standby (spindown) timeout

This way the disk will automatically spin down when there's no activity.

In order to make this change permanent (i.e. after reboot), you may need to make changes to /etc/hdparm.conf. Or maybe, as your distribution is likely nowadays using systemd, you may need to create a unit:

https://unix.stackexchange.com/a/89013/66295

Probably the easiest way would be to use a graphical tool... (yeah, sometimes, when you already have a graphical interface enabled in your system, it is the fastest way)

GUI solution (GNOME)

As you are saying you are using your laptop, I assume you actually have a graphical interface. With GNOME distributions, there's a program named "Disks":

enter image description here

Once you select the hard drive you want to put in standby mode, you can click on "Drive settings" from the menu (or CTRL + E may be a shortcut as well):

enter image description here

Then change the standby timeout settings:

enter image description here

Solution 3

You have an alias! Maybe it's better to have a script that does sync / unmount and then calls hdparm. Add the script to the sudoers file.

cat >/usr/local/sbin/spindown
disk=/dev/disk/by-uuid/c542a956-fbfe-42f7-ac8f-44c029a35a69
sync && unmount /bigdisk/volume &&
hdparam -y $disk

The && makes sure the previous command exits successfully before trying the next.

Then add to sudoers. This might work:

cat >/etc/sudoers.d/spindown <<EOF
ALL ALL=(ALL) NOPASSWD:/usr/local/sbin/spindown
EOF

DanielB made a brilliant suggestion: Use autofs to automatically mount/unmount a local disk (I've never thought of using it that way since I usually work on servers and since autofs was traditionally for NFS). Then once that's set up (don't ask ME how;) ), add something like this to a cronjob:

cat >/etc/cron.d/spindown << EOF
* * * * *  hdparm -C | grep -q -E "idle|active" DISK-DEV && grep -q MOUNTPOINT /etc/mtab && hdparm -y DISK-DEV
EOF

Be sure to replace DISK-DEV and MOUNTPOINT (if Disk-dev has 0 or 1 partition, you can use it for MOUNTPOINT). Please note: I cannot actually test this since the one physical system I have access to ATM is a RAID device and the controller doesn't support those commands.

Solution 4

Here is my hack of a script so far. I will keep this open until somebody finds a better solution...

#!/bin/bash

# for each disk specified as disk
#   if disk is active/idle
#     disk in use as inuse = false
#     for each mount point as mntpoint accociated with it
#       if (lsof | grep mntpoint)
#         inuse = true
#         break
#       endif
#     endfor
#     if inuse
#       spin down disk
#     endif
#   endif
# endfor

DISKS_LEN=1
DISKS[1]=ata-WDC_WD7500BPKX-80HPJT0_WD-WX31AB3N6985

spindown_disk() {
    (sync $1 && sudo hdparm -y /dev/$1 >/dev/null) &
}

diskArr_len=0
for i in `seq $DISKS_LEN`; do
    linkpath=$(readlink /dev/disk/by-id/${DISKS[$i]})
    ((diskArr_len+=1))
    diskArr[$i]=${linkpath##*/}
done

for i in `seq $diskArr_len`; do
    disk=${diskArr[$i]}
    if (sudo hdparm -C /dev/$disk | grep -B1 'active/idle'); then
        inuse=false
        mntpoints="$(mktemp)"
        mount \
            | grep "^/dev/$disk[0-9]" \
            | sed -r "s|^/dev/$disk[0-9] on (.*) type.*$|\1|" \
            >"$mntpoints"
        while read mntpoint; do
            while read openfile; do
                [ $inuse = false ] && echo open files:
                echo $'\t'/${openfile#*/}
                inuse=true
            done < <(lsof | grep "$mntpoint")
        done <"$mntpoints"
        rm -f "$mntpoints"
        if [ "$inuse" = true ]; then
            echo $disk is in use
        else
            echo spinning down $disk \(after sync\)
            spindown_disk $disk
        fi
    else
        echo $disk is already inactive
    fi
done

exit 0

I will still have to figure out how to wrap this up in a systemd service that runs every X minutes. Obviously it would be better if there was an alternative to using lsof and grep. Also, I'm not sure if this would work with funny mount point characters because of the use of grep. Also, it would need to be revised if you had more than 9 partitions.

Please, if you have ANY suggestions don't hesitate.

Share:
21,699

Related videos on Youtube

Shane
Author by

Shane

Updated on September 18, 2022

Comments

  • Shane
    Shane almost 2 years

    I have a laptop with a ssd for primary OS drive, and a large Spinning disk for storage. I currently have an alias I use for manually spinning down the drive when I'm not using it (after umount of course):

    sudo hdparm -y /dev/disk/by-id/ata-WDC_WD7500BPKX-80HPJT0_WD-WX31AB3N6985
    

    Is this safe to use? Will hdparm refuse to do this if the drive has yet to sync or if I forget to umount it? If not, is there a way to use hdparm (or another util) to check if it is safe to do this?


    UPDATE --

    As much as I appreciate both of your answers, they don't help me at all, because I've tried countless different value combinations for the APM and Spin-down time settings, with no results aside from a) less than 10 seconds before spin-down b) no spin-down but random parking, or c) no spin-down or parking. I've also tried to search the web for my specific drive model and its respective APM values, to no avail.

    So, the direction I'd like to go in is this: I need to figure out a way to see if the disk is in use so I can write a systemd service. The closest I can come to so far is lsof | grep /mnt/data, or some such nonesense. But, as you can see, that is far less than ideal. I'd like a method of attaining this that doesn't depend on a predetermined mount point, or the cpu greedy multiple invocations of lsof +D mntpoint in the answer I provided myself.

    Check out my answer below for an idea of what I'm trying to do

    • Nattgew
      Nattgew over 9 years
      I just use the -S option to set a short timeout, that way the device will decide on its own when to spin down.
    • Peque
      Peque about 9 years
      @Shane: well, if it is too short, you can increase the timeout until it is not, right?
  • Daniel B
    Daniel B about 9 years
    Always unmounting the disk isn’t very practical, you could probably work around that with autofs.
  • Otheus
    Otheus about 9 years
    That's a great idea, @DanielB! So get autofs to trigger the unmounting and then let hdparm do its work automatically!
  • Daniel B
    Daniel B about 9 years
    Please note that the APM setting (that hdparm sets) is not working properly on many drives, spinning the drive down after seconds instead of minutes or hours. This can destroy your hard drive.
  • Peque
    Peque about 9 years
    Which GNU/Linux distribution are you using? Which desktop? Why don't you use the -S option (standby when innactive)?
  • Shane
    Shane about 9 years
    it doesn't matter what Linux distribution I am using. So long as hdparm is setting the drive's registers, it's up to the drive to respect them. I can confirm that this is the case as I have tried many different combinations of values passed with -S and -B (check my question edit above). If you're still not convinced, I have had multiple different distros installed on my machine with the same results
  • Peque
    Peque about 9 years
    Well, I think it does. What you want to achieve might be easier with a graphical interface instead of a definitely not-optimal script that you plan on executing every X minutes...
  • Shane
    Shane about 9 years
    A) what do you think the GUI uses as a backend? B) I tried using gnome-disks to do it before I messed with invocating hdparm from a shell
  • Peque
    Peque about 9 years
    A) I don't know, and I guess you neither. ;-) B) Did you find that "standby timeout" option (there's a screenshot in my answer). That didn't work?
  • Shane
    Shane about 9 years
    @Peque I do appreciate your attempt to answer my question though, with screenshots and all
  • Peque
    Peque about 9 years
    So, did you find that "standby timeout" option? (there's a screenshot in my answer). That didn't work? It didn't spin down the drive when innactive? or the timeout didn't work as expected?
  • Shane
    Shane about 9 years
    Thanks man. HD-idle is just what I was looking for. And I've used autofs, don't know why it didn't occur to me to use that with light daemon that spins down unmounted disks.
  • Michael
    Michael almost 6 years
    One reason to manually unmount drives is sleep/resume on a laptop. I'm looking for a way to prevent an HDD from spinning up on resume from sleep, e.g. if it's not mounted. Even if it's not mounted though and I've manually put it to sleep using hdparm, it still is waking up on resume from sleep.
  • Daniel B
    Daniel B almost 6 years
    @Michael When your laptop is in standby, the drive is powered down completely. It must spin up to be detectable again. There is no way around this.