unRaid script to automatically spin up drives when network media player is used


Recommended Posts

OK... I changed the script slightly... basically just two lines need to be replaced in the original. 

 

Instead of relying on the exit status of the "grep" command I am using "cut" with a field delimiter of a space (-d " ") and grabbing the 4th field.  It is the number of pings received.  I can then compare that number with the expected number "1".

 

Ran it all night, with the extra logging enabled, no false detections of a media player online. 

 

These three lines:

            out=`ping -q -c 1 $i 2>/dev/null`

            echo "$out" | grep "received," 1>/dev/null 2>&1

            if [ "$?" = "0" ]

get replaced with these:

            out=`ping -q -c 1 $i 2>/dev/null`

            rec_count=`echo "$out" | grep "received" | cut -d " " -f4`

            if [ "$rec_count" = "1" ]

 

Give it a try and see if it works for you.

 

Joe L.

 

An updated copy of this script is now attached to the first post in this thread (now that attachments are working again)

It will be easiest to download, unzip, and install it from there.

The new script (without all the temporary debugging lines) will then look like this:

#!/bin/bash

######################################################################

#

# Spin up the unRaid disks when a media player is detected on line.

# (it is on line if it responds to a "ping" command over the network)

#

# Joe L.

# January 5, 2008

######################################################################

 

# List the media player IP addresses here.

# separate the IP addresses by spaces if there are more then one

mp_ip="192.168.2.21 192.168.2.22"

last_look_online="no"

 

# Determine if the unRaid array is on-line or not.  If not currently

# started, we do not want to be spinning up any drives.

get_status() {

    cmd status | strings >/tmp/$$spin_up_status

    STATUS=`grep mdState /tmp/$$spin_up_status | cut -d "=" -f2`

    PHYSICAL_DISKS=`grep "^rdevName.*=" /tmp/$$spin_up_status |

        cut -d "=" -f2`

}

 

# function to issue commands to the unRaid "md" device.

# specifically, we will use it to get the status of the array

cmd() {

    echo $* >/proc/mdcmd

    cat /proc/mdcmd

}

 

spin_up_drives() {

    # loop through the drives spinning them up

    # by reading a single "random" block from each disk

    # in turn.  We use "dd" commands in the background so

    # all the disks will be spun up in parallel

    # since the physical disks are listed three times, three random blocks are read from each drive. This should be enough

    # to ensure at least one of the blocks was not in the disk cache memory.

    for i in $PHYSICAL_DISKS $PHYSICAL_DISKS $PHYSICAL_DISKS

    do

        # determine the number of blocks on the drive

        blocks=`df -k /dev/$i | grep -v Filesystem|

        sed "s/\([^ ]*\) *\([^ ]*\) .*/\2/"`

 

        # calculate a (random) block number to be read somewhere

        # between block 1 and the max blocks on the drive

        skip_b=$(( 1+(`dd if=/dev/urandom count=1 2>/dev/null |

        cksum | cut -f1 -d" "`)%($blocks) ))

 

        # read the random block from the disk.  We use a random

        # block to try to ensure it is not in the cache memory

        # if the block was in the cache memory, the disk would

        # not spin up.

        dd if=/dev/$i of=/dev/null \

        count=1 bs=1k skip=$skip_b >/dev/null 2>&1 &

#echo "`date` ****** reading block $skip_b from $i " >>/var/log/spin_up.log

    done

}

 

check_mp_status() {

        mp_online="no"  # initialize to "no" until we learn otherwise

        # ping each of the media servers to determine if online

        for i in $mp_ip

        do

            # ping the media server, if it answers, it is online

            # echo "$out" | grep "received," 1>/dev/null 2>&1

            out=`ping -q -c 1 $i 2>/dev/null`

            rec_count=`echo "$out" | grep "received" | cut -d " " -f4`

            if [ "$rec_count" = "1" ]

            then

                mp_online="yes"

                # if one is online, we do not need to ping

                # any others, break out of the "for" loop.

                break;

            fi

        done

echo $mp_online

}

 

sleep_checking_status() {

    seconds_to_sleep=$1

    test_interval=10

    while  ( test $seconds_to_sleep -gt 0 )

    do

      get_status

      if [ "$STATUS" != "STARTED" ]

      then

          break

      fi

      sleep $test_interval

      seconds_to_sleep=$(( $seconds_to_sleep - $test_interval ))

    done

}

 

# create a lockfile so we do not start two of these spin_up processes

lockfile="/var/lock/spin_up_drives"

 

if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null;

then

  trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT

 

  echo "`date` ****** spin_drives.sh started" >/var/log/spin_up.log

 

  # loop forever

  while true

  do

    get_status

    if [ "$STATUS" != "STARTED" ]

    then

        # if the array is not started, sleep a few seconds and loop to

        # check status once more

        sleep 2

    else

        # The array is started, see if any of the media players are

        # on-line. If they are, spin up the drives if we need to.

 

        online="no"  # initialize to "no" until we learn otherwise

        online=`check_mp_status`

 

        # if any media players are online, spin up the drives

        # and then sleep checking for status changes and we'll

        # see if they are still online next time through the loop.

 

        if [ $last_look_online = "no" ]

        then

            if [ $online = "yes" ]

            then

              last_look_online="yes"

              echo "`date` media player is online..." >>/var/log/spin_up.log

            fi

      else # last_look_online = yes

            if [ $online = "no" ]

            then

              last_look_online="no"

              echo "`date` media player offline..." >>/var/log/spin_up.log

            fi

      fi

      if [ $online = "yes" ]

      then

          spin_up_drives

          # we just spun up the drives, we don't need to do much

          # for the next 600 seconds unless the

          # array status changes, so sleep looking for changes

          sleep_checking_status 600

      else

          sleep 5

      fi

 

    fi

  done

 

    rm -f "$lockfile"

    trap - INT TERM EXIT

else

    echo "Failed to acquire lockfile: $lockfile."

    echo "Held by $(cat $lockfile)"

fi

 

Link to comment

Seems to be working just fine Joe! :)

 

Not sure how long it took, but it's been a couple of hours since I last switched the media player on and all drives have happily spun down!

 

Great stuff!

 

Thanks again,

 

Mark.

 

[EDIT] Another startup of the MediaPlayer and all HDDs up again, another hour or so of no use and all have successfully spun down again! :D

Link to comment
  • 2 months later...
  • 11 months later...

I love this script.  It makes having a media server work with unRAID so much more enjoyable.  It works great with XBMC on the orginial XBOX (kind of, see below).

 

However, after leaving it running for a while something goes wrong.  When I look at the top command I see that spin_drives.sh is maxing out one of my CPUs at 100%. 

 

top - 20:36:37 up 8 days,  2:44,  2 users,  load average: 1.03, 1.09, 1.05
Tasks:  92 total,   2 running,  89 sleeping,   0 stopped,   1 zombie
Cpu(s): 50.0%us,  0.0%sy,  0.0%ni, 50.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   4151240k total,  4097816k used,    53424k free,   208140k buffers
Swap:  4249152k total,      156k used,  4248996k free,  3353284k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
21129 root      20   0  4140 2288  312 R  100  0.1   4102:31 spin_drives.sh

 

When I look at the running processes I can actually see two instances of spin_drives.sh.  Is that correct?

 

root     29570     1  0  1035  2888   0 Mar12 ?        00:00:17 /bin/bash /boot/spin_drives.sh
root     21129 29570 99  1035  2288   0 Mar13 ?        2-20:19:07  \_ /bin/bash /boot/spin_drives.sh

I don't see anything in my syslog pertaining to this but could easily post one if someone thought it would help out.  Does anybody else have this problem or have a suggestion as how to fix it?

 

Thanks very much.

Link to comment
  • 2 years later...

I just found this post, and couldn't find anything newer discussing it, so I'm resurrecting it :)

 

If I understand correctly, this script will ping any of the IP addresses I fill in, and if any of them respond, it will spin up the drives, as long as the array is running.  A very clever idea actually, thanks for sharing!

 

Now, the reason I'm bringing out of the "old, forgotten posts" bin, is to ask if

 

A) is there any reason this won't work with 5b13?  Or, any changes that I need to make to it now?

 

B) how might one amend the script so that if/when NONE of the IP addresses respond, it spins them down?  I have it set to spin down after 45 minutes, but if I shut off the receiver, and HTPC and my Desktop, no one will need the drives spinning, so I might as well force them to spin down now, and not wait another 45 mintues, no?  I can set agressive sleep policies on the other machines, to shut them down quickly, so why not propigate that onto the server?

 

C) will this script still work if I force unRAID into sleep mode?  Or will I need to have all machines send a magic packet upon startup in that case?

 

Thanks again for being so generous with your clever talents, they have been very useful to me the last month or so, since I discovered unRAID  :D

 

 

Link to comment
  • 3 months later...
  • 1 year later...

This is definitely a nice concept -- hopefully Joe will update it so it works with v5.

 

It seems that one thing you'd want to do is reserve IPs in your router so the media player(s) always get the same IP  [or just use static IPs ... which may not be a good choice if you have portable units that are sometimes connected elsewhere].

 

Link to comment

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.