5

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

3
  • 1
    I just use the -S option to set a short timeout, that way the device will decide on its own when to spin down.
    – Nattgew
    Dec 15, 2014 at 21:02
  • Hmm.. I've tried setting short timeout and It is way too short for my taste (I don't want to wear out the drive quickly). I've since contacted WD (my drive manufacturer), and they told me only their enterprise class drives support features like this.
    – Shane
    May 9, 2015 at 9:48
  • @Shane: well, if it is too short, you can increase the timeout until it is not, right?
    – Peque
    May 11, 2015 at 7:58

4 Answers 4

5
+50

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.

3
  • 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.
    – Shane
    May 15, 2015 at 23:05
  • 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.
    – Michael
    Jul 7, 2018 at 16:32
  • @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.
    – Daniel B
    Jul 8, 2018 at 9:58
4

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.

2
  • 2
    Always unmounting the disk isn’t very practical, you could probably work around that with autofs.
    – Daniel B
    May 9, 2015 at 18:30
  • That's a great idea, @DanielB! So get autofs to trigger the unmounting and then let hdparm do its work automatically!
    – Otheus
    May 9, 2015 at 18:37
4

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

1
  • 1
    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.
    – Daniel B
    May 11, 2015 at 9:16
2

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.

7
  • Which GNU/Linux distribution are you using? Which desktop? Why don't you use the -S option (standby when innactive)?
    – Peque
    May 12, 2015 at 8:51
  • 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
    – Shane
    May 12, 2015 at 9:01
  • 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...
    – Peque
    May 12, 2015 at 9:06
  • 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
    – Shane
    May 12, 2015 at 9:07
  • 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?
    – Peque
    May 12, 2015 at 9:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .