Advanced disk spindown


Recommended Posts

After my my Western Digital WD180EDFZ disks did not spindown (while usual WD Ultrastar disks work flawlessly) I wrote this script to obtain the different power modes (which aren't checked by Unraid) and I found out that some disks are randomly lying (!) like returning "STANDBY" while they are spinning!

 

What the script does:

  1. It checks if the icon in the Unraid WebGUI has the correct color (active / standby) and corrects it if necessary
  2. It checks the spin down state of Disks that claim to be in STANDBY
    Note: This is done by repeating Unraid's spin down command. Regarding my measurements, this re-execution lowers the power consumption even more. I think because the SATA ports itself were not in standby after the first spindown command.
  3. Option: Spindown disks that are in the advanced idle modes "IDLE_B" and "IDLE_C"
    Note: Some disks aren't spinning although they return these states.
  4. It optionally sets the spindown timer of the disk's firmware
    Note: Its set and removed every 32 minutes if the disk stays active. This trick helps as some disks ignore the first try.

 

Donate? 🤗

 

Manual:

- This script should be executed by the "CA User Scripts" plugin which can be installed through "Apps"

- Use the custom cron schedulde */15 * * * * to execute it every 15 minutes

- Check the "Settings" inside the script

 

#!/bin/bash
# #####################################
# Script:      Advanced disk spindown v0.4
# Description: Monitors disks power modes, spins down disks and corrects 
#              Unraid's WebGUI icon if necessary.
# Author:      Marc Gutt
# 
# Changelog:
# 0.4
# - complete rewrite
# - icon is now only corrected if necessary
# - measure execution time of spin up command as well
# - reading bytes through dd is replaced by Unraid's spinup command
# 
# ######### Settings ##################

# set to "1" to enable spinning down disk if power mode is IDLE_A
idle_b_spindown=1

# set to "1" to enable spinning down disk if power mode is IDLE_B
idle_c_spindown=1

# set to "1" to enable spindown timer through "smartctl -s standby,241 /dev/sdb". "241" means 30 minutes
advanced_spindown=0

# #####################################
# 
# ######### Script ####################
# make script race condition safe
if [[ -d "/tmp/${0///}" ]] || ! mkdir "/tmp/${0///}"; then exit 1; fi; trap 'rmdir "/tmp/${0///}"' EXIT;
# loop through devices
for devpath in /dev/sd?; do
    runtime=""
    # obtain disk id and name
    devname=${devpath: -3}
    diskid=$(grep -oP "(?<=rdevName\.)[0-9]+(?==${devname})" /proc/mdstat)
    # skip non-array disks
    if [[ -z $diskid ]]; then
        continue
    fi
    diskname=$(grep -zoP "(?<=name=\")[a-z0-9]+(?=\"\ndevice=\"${devname})" /var/local/emhttp/disks.ini | tr -d '\0')
    if [[ -z $diskname ]]; then
        echo "Diskname of Disk ${diskid} (${devname}) not found!"
        continue
    fi
    # obtain power mode
    devinfo=$(smartctl -n standby -i $devpath)
    modes=( IDLE_A IDLE_B IDLE_C STANDBY ACTIVE UNKNOWN )
    for mode in "${modes[@]}"; do
        if [[ $devinfo == *"${mode}"* ]]; then
            break
        fi
    done
    # obtain WebGUI icon
    icon=$(sed -e "/device=\"${devname}\"/,/fsStatus/!d" /var/local/emhttp/disks.ini)
    if [[ $icon == *"green-blink"* ]]; then
        icon="STANDBY"
    elif  [[ $icon == *"green-on"* ]]; then
        icon="ACTIVE"
    else
        icon="UNKNOWN"
    fi
    echo -n "${diskname} (${devname}), ${mode} mode, ${icon} icon"
    general_mode="STANDBY"
    if [[ ${mode} == *"IDLE_"* ]] || [[ ${mode} == "ACTIVE" ]]; then
        general_mode="ACTIVE"
    fi
    # icon correction
    if [[ ${general_mode} != ${icon} ]]; then
        echo -n " (wrong)"
        # update icon
        if [[ $general_mode == "ACTIVE" ]]; then
            start=$(date +%s)
            /usr/local/sbin/emcmd cmdSpinup=${diskname}
            end=$(date +%s)
            runtime=$((end-start))
            # as the disk is active it should already spin
            if [[ $runtime -gt 1 ]]; then
                echo -n ", Warning: Unexpected spin up while icon correction!"
            fi
        else
            start=$(date +%s)
            /usr/local/sbin/emcmd cmdSpindown=${diskname}
            end=$(date +%s)
            runtime=$((end-start))
            # as the disk is in standby mode it should already stand still
            if [[ $runtime -gt 1 ]]; then
                echo -n ", Warning: Unexpected spin down while icon correction!"
            fi
        fi
        echo -n ", Icon has been corrected."
    else
        echo -n " (correct)"
    fi
    # spin down disk although it is already in STANDBY mode as some disks are lying regarding their spinning state
    if [[ $mode == "STANDBY" ]] && [[ -z $runtime ]]; then # runtime is only empty if icon correction wasn't necessary
        echo -n ", Check spin down state"
        start=$(date +%s)
        /usr/local/sbin/emcmd cmdSpindown=${diskname}
        end=$(date +%s)
        runtime=$((end-start))
        # as the disk is in standby mode it should already stand still
        if [[ $runtime -gt 1 ]]; then
            echo -n ", Warning: Disk unexpectedly spun down!"
        else
            echo -n ", Good: Disk already stands still."
        fi
    fi
    # spin down disks that are in advanced idle modes
    if [[ $mode == "IDLE_B" ]] && [[ $idle_b_spindown == "1" ]] || [[ $mode == "IDLE_C" ]] && [[ $idle_c_spindown == "1" ]]; then # runtime is only empty if icon correction wasn't necessary
        echo -n ", Check spin down state"
        start=$(date +%s)
        /usr/local/sbin/emcmd cmdSpindown=${diskname}
        end=$(date +%s)
        runtime=$((end-start))
        # as the disk is in standby mode it should already stand still
        if [[ $runtime -gt 1 ]]; then
            echo -n ", Good: Spin down was successful!"
        else 
            echo -n ", Warning: Unexpected stagnant disk, sent to STANDBY!"
        fi
    fi
    # set spindown timer (some disks need it)
    last_spindown="/tmp/ForceSpindown${diskid}.last"
    if [[ $advanced_spindown == "1" ]]; then
        if [[ $mode == "IDLE_A" ]]; then
            # Remove spindown timeout (some disks react only on the second try)
            if [[ -f ${last_spindown} ]]; then
                time_last=$(stat -c %Y ${last_spindown})
                time_expired=$((time_last+1920)) # 1920 = 32 minutes
                time_now=$(date +%s)
                if [[ $time_expired -lt $time_now ]]; then
                    echo -n ", removed spindown timer"
                    smartctl -n standby -q errorsonly -s standby,off $devpath
                    rm ${last_spindown}
                fi
            # Set spindown timeout
            else
                echo -n ", set spindown timer"
                smartctl -n standby -q errorsonly -s standby,241 $devpath # 241 = 30 minutes
                touch ${last_spindown}
            fi
        fi
    # remove spindown timer
    elif [[ -f ${last_spindown} ]]; then
        last_spindown="/tmp/ForceSpindown${diskid}.last"
        smartctl -q errorsonly -s standby,off $devpath
        rm ${last_spindown}
        echo -n ", removed spindown timer"
    fi
    echo ""
done

 

 

Execute this to manually spin down all disks:

for dev in /dev/sd?; do /usr/local/sbin/emcmd cmdSpindown="$(grep -zoP "(?<=name=\")[a-z0-9]+(?=\"\ndevice=\"${dev: -3})" /var/local/emhttp/disks.ini | tr -d '\0')"; done

 

  • Thanks 1
Link to comment

Example log output:

Script Starting Apr 20, 2021 00:30.01

Full logs for this script are available at /tmp/user.scripts/tmpScripts/forcespindown/log.txt

Spin down Disk 4 although it is already in STANDBY state to force icon change in Unraid WebGUI... has been spun down.
Error: As the Disk already was in STANDBY state, this should not happen!
Spin down Disk 6 although it is already in STANDBY state to force icon change in Unraid WebGUI... was already spun down.
Spin down Disk 3 although it is already in STANDBY state to force icon change in Unraid WebGUI... was already spun down.
Spin down Disk 10 although it is already in STANDBY state to force icon change in Unraid WebGUI... was already spun down.
Spin down Disk 1 although it is already in STANDBY state to force icon change in Unraid WebGUI... was already spun down.
Spin down Disk 0 although it is already in STANDBY state to force icon change in Unraid WebGUI... was already spun down.
Skip Disk 8 as it is in ACTIVE state, but we read some bytes to force icon change in Unraid WebGUI.
Spin down Disk 2 although it is already in STANDBY state to force icon change in Unraid WebGUI... was already spun down.

Script Finished Apr 20, 2021 00:30.08

 

 

Link to comment
1 hour ago, ChatNoir said:

when you are able to update

Why "you"? I'm not a Limetech Dev 😉

 

PS It does not work perfectly. I still have disks not staying spun down (which isn't visible in the WebGUI) or spinning down at all. I will update my script and output more to the logs to find the reason.

Link to comment

Updated to version 0.2. New features:

# - measure execution time of the spindown command to find out if the disk was already spun down or not
# - read 512 bytes if the disk is in ACTIVE state to force icon change in Unraid WebGUI
# - return error message for disks that were spun down although they already should

 

Link to comment

I proudly present version 0.3:

# - bug fix: Save timestamp of last spindown setting for each disk and not only the first (last_spindown)
# - set/remove firmware standby timer is moved to IDLE_A state to avoid waiking up the disk(s)
# - set/remove firmware standby timer is delayed by 32 minutes
# - cleaner logs by removing output of smartctl and dd

 

Link to comment

I checked my logs since yesterday and I'm shocked how often some disks are spinning altough they return a STANDBY state:
 

########################################################################
Script Starting Jun 03, 2021  17:15.01
Spin down Disk 2 although it is in STANDBY state. Forces WebGUI icon change... has been spun down (Should not happen!)
########################################################################
Script Starting Jun 04, 2021  09:15.01
Spin down Disk 3 although it is in STANDBY state. Forces WebGUI icon change... has been spun down (Should not happen!)
########################################################################
Script Starting Jun 04, 2021  12:45.01
Spin down Disk 2 although it is in STANDBY state. Forces WebGUI icon change... has been spun down (Should not happen!)
########################################################################
Script Starting Jun 04, 2021  13:30.01
Spin down Disk 4 although it is in STANDBY state. Forces WebGUI icon change... has been spun down (Should not happen!)
########################################################################
Script Starting Jun 04, 2021  17:45.01
Spin down Disk 4 although it is in STANDBY state. Forces WebGUI icon change... has been spun down (Should not happen!)
########################################################################
Script Starting Jun 04, 2021  18:00.01
Spin down Disk 1 although it is in STANDBY state. Forces WebGUI icon change... has been spun down (Should not happen!)
########################################################################

 

 

Link to comment
  • mgutt changed the title to Advanced disk spindown

Released v0.4

# - complete rewrite
# - icon is now only corrected if necessary
# - measure execution time of spin up command as well
# - reading bytes through dd is replaced by Unraid's spinup command

 

The log output is now different, too:

Script Starting Jun 05, 2021 14:45.01
disk4 (sdc), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk6 (sdd), IDLE_A mode, ACTIVE icon (correct)
disk3 (sde), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk10 (sdf), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk1 (sdg), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
parity (sdh), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk8 (sdi), ACTIVE mode, ACTIVE icon (correct)
disk2 (sdj), IDLE_A mode, ACTIVE icon (correct)
Script Finished Jun 05, 2021 14:45.06

Script Starting Jun 05, 2021 15:00.01
disk4 (sdc), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk6 (sdd), IDLE_A mode, ACTIVE icon (correct)
disk3 (sde), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk10 (sdf), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk1 (sdg), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
parity (sdh), STANDBY mode, STANDBY icon (correct), Check spin down state, Good: Disk already stands still.
disk8 (sdi), ACTIVE mode, ACTIVE icon (correct)
disk2 (sdj), IDLE_B mode, ACTIVE icon (correct), Check spin down state, Warning: Unexpected stagnant disk, sent to STANDBY!
Script Finished Jun 05, 2021 15:00.07

 

As you can see disk2 claimed to be in IDLE_B mode, but the spindown command was executed in less than 1 second, which means the disk already wasn't spinning. Because of that the script finally send disk2 to STANDBY.

Link to comment
  • 2 years later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.