WD Scorpio blue 640 Gb drive
WD Scorpio Blue 640 Gb 2.5″ hard drive.

Western Digital mobile hard drives, at least 640 Gb model, have some unpleasant features on Mac OS X, regardless whether is it a root volume or an external drive. When idle, disk spins down and then spins up several times a minute. Mac OS X’s power saving settings do not matter. This behavior is not only annoying but also harmful for the device.

Community offers an efficient solution: HDAPM. This utility changes the power management settings for the device directly so it runs constantly. However hdapm works only with internal SATA drives and inapplicable with external drives connected by USB. So another solution is wanted.

My idea was to send the drive filesystem some tasks repeated with some interval. Initially I created this with AppleScript, but after N cycles (I do not know exactly how many) it reported “Stack overflow” error. Then I decided to migrate the script to bash engine. It seems to be simpler and I suppose will not give that stupid errors.

Here you can find a working script. It uses some variables such as disk name (or name of its first partition), notification type (text output in Terminal window or by Voice).

To use the script, copy the text below, paste it into a text editor, edit the disk_name variable and save with .command extension.
Create a blank (or a small text) file named driveWakeUp at the drive’s root.
Now you can run the script:

#/bin/bash
disk_connected=0
disk_name="WD 640 Gb"
disk_path="/Volumes/$disk_name"
waker_file="$disk_path/driveWakeUp"
waker_filecp="$disk_path/driveWakeUp0"
string_connected="Backup drive connected."
string_disconnected="Backup drive disconnected."
string_activated="Disk waker activated."
string_voice="Victoria"
voice_output=true
cycle_number=0
cycles_number=60*60*24*7*4
echo "Target disk is "$disk_name"."

reportDriveStatus () {
disk_connected_prev=$disk_connected
checkDriveStatus
if ! [ "$disk_connected" = "$disk_connected_prev" ]
then
if [ "$disk_connected" = 1 ]
then
if $voice_output
then
say -v "$string_voice" "$string_connected"
else
echo "$string_connected"
fi
else
if $voice_output
then
say -v "$string_voice" "$string_disconnected"
else
echo "$string_disconnected"
fi
fi
fi
}

checkDriveStatus () {
disks_count=0

if [ -d "$disk_path" ]
then
disk_connected=1
else
disk_connected=0
fi
}

wakeDrive() {
if [ -f "$waker_filecp" ]
then
rm "$waker_filecp"
else
cp "$waker_file" "$waker_filecp"
fi
}

if $voice_output
then
say -v "$string_voice" "$string_activated"
else
echo "$string_activated"
fi

coreCycle() {
for ((i=1; i <= cycles_number ; i++))
do
reportDriveStatus
# echo -n "$i "
if [ "$disk_connected" = 1 ]
then
wakeDrive
sleep 1
else
sleep 15
fi
done
}

coreCycle

Okay, I also could dedicate a separate function for notifications, but I was lazy to the time (:

Leave a Reply