5

I'm trying to get my NAS server to wake from an S3 sleep state when the NAS is accessed by a user. I want to do this to increase the longevity of the server, and also to limit its power usage. I've seen people asking for similar advice but none that I found provide a robust solution, most threads just ended unanswered.

So to just detail my problem quickly: At my home I have a custom built, from an old PC, NAS server, running Ubuntu server, which stores media and documents mainly. This server is currently set to sleep after a predefined inactive period. Currently the NAS can be brought out of the S3 state with a WOL magic packet. What I would like to achieve is that this magic packet is automatically sent to the server when a user accesses one of the shares from their PC. The users are primarily running windows 7. I'm not sure if this is entirely prevalent but I have a Linksys WRT54G running DD-WRT as my home router/DHCP/DNS.

During my research I came across many articles which just automatically woke the server on a timed loop, no real intelligence. The article given below seems to do what I want:

http://wdtvhd.com/index.php?showtopic=7908

A script is given which attempts to address this problem by using the DD-WRT router to send the wake-on-lan packets when a query is made. This seems like a good way to go about this, however I could not get the script given in the link to operate correctly.

I think that covers most aspects of my problem. Any assistance will be greatly appreciated.

Rabid
  • 326
  • 4
  • 14
  • You might have better luck on ServerFault. The solution in http://serverfault.com/questions/389286/automatic-wake-on-lan-in-linux-when-accessing-remote-filesystem might help, although this would involve accessing the share data via the always-on WRT54G which may be a bottleneck. – George Aug 16 '12 at 12:57

3 Answers3

4

Just thought I would post my eventual solution to the above mentioned problem. To solve the problem I wrote a custom script which runs on my dd-wrt router on a timed cron job. When this script runs it access the file

\proc\net\arp

Within in that file is stored a record of all currently leased IP address and the corresponding mac addresses. Thus my script compared the mac addresses stored within that file to a predefined list of mac address of PCs on my home network. The list is comprised only of the PCs I would like to be able to access the NAS server. If one of the PCs is found to have an active lease the router then sends the wake-on-lan magic packet. Which then wakes the server. At that point I thought I had achieved my goal, as the server switched on with any of the PCs on the network, and the wait was not too long. However, after completing this I found that my timed sleep for the server would initiate every 30 min or so and sleep the server only to be woken again a couples of seconds later.

So to solve that issue I just added another condition to my conditional statement that would sleep the server if none of the required PC had an active lease. To do this I used SSH and the built in dropbear ssh functionality of DD-WRT to sleep the server. Below is the script

#!/bin/ash

NAS="MA:CA:DD:RE:SS:00"

PC="MA:CA:DD:RE:SS:00"

varP='grep -o $PC /proc/net/arp'

while true
do
    echo 'Entered Loop'
    if ping -c 1 IPADDRESSOFNAS > /dev/null; then
            echo 'NAS is Already ON'

    if [[ "$varP" != "MA:CA:DD:RE:SS:00" ]]; then
                    echo 'All Hosts Offline'
                    echo IPADDRESSOFNAS  ssh-rsa NASPUPLICKEY
                    #HOME=/temp/root/
                    DROPBEAR_PASSWORD='NASPASSWORD' ssh root@IPADDRESSOFNAS pm-suspend &
            fi
            exit
    fi

    if [[ "$varP" == "MA:CA:DD:RE:SS:00" ]]; then
            echo 'waking from lan'
            /usr/sbin/wol -i BROADCASTADDRESSOFNETORK -p 9 MA:CA:DD:RE:SS:00
            /usr/sbin/wol -i BROADCASTADDRESSOFNETORK  -p 9 MA:CA:DD:RE:SS:00
            exit
    fi
    exit
done

DISCLAMER: The code is supplied as is. I am aware it is not pretty nor the best solution possible. But it works for me and thats all I really need.

Hope someone finds this useful!

Rabid
  • 326
  • 4
  • 14
  • Would it be possible to see the format of your `\proc\net\arp` file? – Colin747 Nov 24 '13 at 23:53
  • This looks incredible and should work fine to WOL any computer accessing samba since this is not OS dependant. My HTPC actually runs Windows 8.1 as it serves both hosting and playing media. I will try to get my hands on a better router that supports dd-wrt and gives this a try. – dan Apr 24 '14 at 01:05
  • Yes it should, as long as your NIC on the HTPC (or other PCs) are able to interpret WOL Magic packets it should work. Check out [link](http://www.dd-wrt.com/site/support/router-database) you may be pleasantly surprised that your router is supported. – Rabid Apr 24 '14 at 07:03
0

I insprected my NAS from WD and I can tell you that they uses memory drives for the /tmp, /var directories.

So are every logs written to the memory and the harddrive has not to be online. Hope that helps you a bit.

If someone want to access the harddrive the system will automatically upspinn your harddrive. So you will get what you want except that the system is always online.

rekire
  • 47,260
  • 30
  • 167
  • 264
  • I think you might be misunderstanding slightly, my NAS is not a prepackaged standalone (such as those available from seagate and WD etc). Rather it is one of my old PCs that I re-purposed into a NAS. – Rabid Jun 06 '12 at 10:03
  • I wrote this answer in the mention that you try to save energy. If yor harddrives are offline you will save energy. – rekire Jun 06 '12 at 10:10
  • Fair enough, I already configured Ubuntu to spin the drives down when in active. However, I would like to power down the entire machine and not just the drives. – Rabid Jun 06 '12 at 10:18
  • On my own box I have the problem when I try to spin the drives out that they will wake some seconds later up for writeing some useless stuff to the headdrive. The solution with the memory drive would help me if that machine would have enough momory. I you don't like my answer at all I can delete it :-) – rekire Jun 06 '12 at 10:23
  • No thats fine, your answer might help someone else down the line. My drives spin down fine, as they are not the primary drives. I think you would struggle to spin down the drive with the bootable partition. – Rabid Jun 06 '12 at 10:25
  • Indeet that box has just one drive. – rekire Jun 06 '12 at 10:29
0

I made some changes to the script by @Rabid to add support for multiple PCs.

It also checks whether the entries found in ARP have their flag set to 0x2 ( =~ active ), as, for me, the ARP entries would remain listed for too long after the PC had gone offline.

#!/bin/bash
# This script is made to be run on an DD- / Open-WRT device to automatically wake a NAS 
# server if client PCs are online

# Settings

# Addresses of NAS that gets woken / put to sleep
MACofNAS="MA:CA:DD:RE:SS:00"
IPofNAS="192.168.2.1"
BroadcastAddress="192.168.2.255"
WOLPort=9

# Location of SSH Private Key on WRT (if used for login)
SSHPrivateKeyFile=~/.ssh/id_rsa

# MAC addresses of PCs of which the online status will be checked
PCs=(
    "MA:CA:DD:RE:SS:00" # PC1
    "MA:CA:DD:RE:SS:00" # PC2
    "MA:CA:DD:RE:SS:00" # PC3
    "MA:CA:DD:RE:SS:00" # PC4
)



# Determine if any PCs are on
SomePCisON=false
for index in ${!PCs[@]}; do
    # Try to detect PC's MAC address in ARP

    ## Look for all entries in ARP ...
    # PCFound=$(grep -o "${PCs[index]}" /proc/net/arp)

    # ... OR look only for entries with flag set to 0x2 ( ~ active )
    PCFound=$(grep "0x2" /proc/net/arp | grep -o "${PCs[index]}") 

    # If MAC address is found, the PC must be ON
    if [[ ${PCFound} ]]; then
        echo "PC ${PCs[index]} is ON"
        SomePCisON=true
    else
        echo "PC ${PCs[index]} is OFF"
    fi
done

if [[ "$SomePCisON" == true ]]; then
    echo "Some PCs are turned ON"
else
    echo "All PCs are turned OFF"
fi

# Check if NAS is ON
if ping -c 1 $IPofNAS > /dev/null; then
    echo 'NAS is ON'
    NASisON=true
else
    echo 'NAS is OFF'
    NASisON=false
fi

# If NAS is ON, but all PCs are OFF, put NAS to Sleep
if [[ "$NASisON" == true ]]; then

    # If no PCs are ON, put NAS to sleep
    if [[ "$SomePCisON" == false ]]; then
            echo 'All Hosts Offline'
            echo 'Suspending NAS'

            # Log in with password (as in @Rabid's script, didn't work for me) ...
            DROPBEAR_PASSWORD='NASPASSWORD' ssh root@IPADDRESSOFNAS pm-suspend &

            ## ... OR log in with authentication key
            # ssh -i $SSHPrivateKeyFile root@$IPADDRESSOFNAS pm-suspend &
    fi

# If NAS is OFF and any PCs are ON, wake NAS
elif [[ "$SomePCisON" == true ]]; then

    # Use wol package on DD-WRT ...
    echo 'Waking NAS from LAN, Broadcasting to '$BroadcastAddress\
        'on port '$WOLPort' for '$MACofNAS
    /usr/sbin/wol -i $BroadcastAddress -p $WOLPort $MACofNAS
    /usr/sbin/wol -i $BroadcastAddress -p $WOLPort $MACofNAS;

    ## ... OR use etherwake package on Open-WRT 
    ## ( Install with: opkg update && opkg install etherwake )
    # echo 'Waking NAS from LAN, '$MACofNAS
    # /usr/bin/etherwake $MACofNAS
    # /usr/bin/etherwake $MACofNAS
fi

To log in with an authentication key, make a key pair and place the public key in NAS:~/.ssh/authorized_keys:

On WRT (with Dropbear):

mkdir -p ~/.ssh

# Generate a private key and store it in ~/.ssh/id_rsa
dropbearkey -t rsa -f ~/.ssh/id_rsa

# Store the public key in ~/.ssh/id_rsa.pub
dropbearkey -t rsa -f ~/.ssh/id_rsa -y | grep ssh > ~/.ssh/id_rsa.pub

# Copy id_rsa.pub from WRT:~/.ssh/ to NAS:~/.ssh/
scp ~/.ssh/id_rsa.pub root@nas:~/.ssh/OpenWRT.pub 

On NAS (with OpenSSH):

# Back up the authorized_keys
cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys_Backup

# Add the new public key to authorized_keys
cat ~/.ssh/OpenWRT.pub >> ~/.ssh/authorized_keys
Lau
  • 1
  • 1