Asustor 廉価版 NAS AS1xx4T の省エネ化 - その22021/09/18 00:00

事前準備
- NAS に、admin 権限のアカウントを作っておく(例えば adminx). admin アカウントを使ってもいいが、この目的専用の password にしておきたかった、というだけの理由。
- NAS の ssh サービスを有効にしておく
- 同じネットワーク上に常時動作してある linux を使う (Raspberry PI など)

下記 5 つのファイルを作成し、Linux host で crontab 設定する。

NASをリモート起動する場合は、WOL を使用(NAS の WOL 設定をお忘れなく)。

1) auto_poweroff.sh - NAS 上で動かすスクリプト
#!/bin/sh
PASSWD="adminx アカウントのパスワード平文"
SMBLOG="./smbstatus.log"
NSLOG="./netstat.log"
LOCKFILE="./auto_poweroff.lock"

## RAID scrubbing check
ps -ef | grep  "\[md1_resync\]"
if [ $? -eq 0 ]; then exit 0; fi
## RAID scrubbing check -- end

## established session check (UPNP, ftp, sftp, ssh)
netstat -ut > $NSLOG
M=`cat $NSLOG | wc -l`
while [ $M -gt 0 ]; do
        LINESTR=`sed -n $M\P $NSLOG`
        echo $LINESTR | grep -E "^(tcp|udp)" > /dev/null
        if [ $? -eq 0 ]; then
                SESSION=`echo $LINESTR | awk -F' ' '{print $6}'`
                if [ $SESSION = "ESTABLISHED" ]; then
                        IPPORT=`echo $LINESTR | awk -F' ' '{print $4}'`
                        echo $IPPORT | grep -E ":(5001|2222|ftp)$" > /dev/null
                        if [ $? -eq 0 ]; then break; fi
                        echo $IPPORT | grep -E ":ssh$" > /dev/null
                        if [ $? -eq 0 ]; then
                                CLIENT=`echo $LINESTR | awk -F' ' '{print $5}'`
                                CLIENTNAME=`echo $CLIENT | sed -e "s/^\(.\+\):[0-9]\+$/\1/g"`
                                IPADDR=`nslookup $CLIENTNAME | grep "Address" | tail -n 1 | sed -e "s/^Address.*:[ \t]\+\([0-9a-fA-F.:]\+\).*/\1/g"`
                                IPPORT="$IPADDR:`echo $CLIENT | sed -e "s/^.\+:\([0-9]\+\)$/\1/g"`"
                                SSHCLIENT="`echo $SSH_CLIENT | awk -F ' ' '{print $1}'`:`echo $SSH_CLIENT | awk -F ' ' '{print $2}'`"
                                if [ $IPPORT != $SSHCLIENT ]; then break; fi
                        fi
                fi
        fi
        M=`expr "$M" - 1`
done

if [ $M -gt 0 ]; then
        echo "$LINESTR"
        rm -f $LOCKFILE
        exit 0
fi
## UPNP session check -- end

## samba session check
echo $PASSWD | sudo -S /usr/builtin/bin/smbstatus -A > $SMBLOG
N=`cat $SMBLOG | wc -l`
while [ $N -gt 0 ]; do
        IPADDR=`sed -n $N\P $SMBLOG | awk -F' ' '{print $5}'`
        echo $PASSWD | sudo -S ping -c 1 -W 3 $IPADDR > /dev/null
        if [ $? -eq 0 ]; then break; fi
        N=`expr "$N" - 1`
done

if [ $N -gt 0 ]; then
        echo "IP $IPADDR is alive."
        rm -f $LOCKFILE
        exit 0
fi

if [ -e $LOCKFILE ]; then
        echo 'Execute poweroff'
        rm -f $LOCKFILE
        echo $PASSWD | sudo -S poweroff
        exit 2
else
        echo 'Check one more time later'
        echo -n > $LOCKFILE
fi

exit 1
2) sendscript.sh - 上記実行ファイルの転送と実行を host 上で行う script
#!/bin/bash
if [ $# -ne 1 ]; then
        echo "Usage: $0 [nas_server_address]"
        exit 2
fi

THIS_FILE_PATH=`dirname $0`
PASSWD="adminx アカウントのパスワード平文\n"

echo "["`date "+%Y%m%d_%H%M"`"]"

ping -c 1 -W 3 $1 > /dev/null
if [ $? -ne 0 ]; then
        echo "Target $1 in power-off. Quitting..."
        exit 1
fi

expect -c "
        set timeout 30
        spawn $THIS_FILE_PATH/chkfile.sh $1
        expect \"Password:\"
        send $PASSWD
        expect eof
        catch wait result; exit [lindex \$result 3]
"

if [ $? -ne 0 ]; then
        expect -c "
                set timeout 30
                spawn $THIS_FILE_PATH/scp.sh $1
                expect \"Password:\"
                send $PASSWD
                expect eof
                catch wait result; exit [lindex \$result 3]
        "
fi

expect -c "
        set timeout 30
        spawn $THIS_FILE_PATH/ssh.sh $1
        expect \"Password:\"
        send $PASSWD
        expect eof
        catch wait result; exit [lindex \$result 3]
"
3) scp.sh - 実行ファイル転送サブ・スクリプト
#!/bin/bash
THIS_FILE_PATH=`dirname $0`
scp -p $THIS_FILE_PATH/auto_poweroff.sh adminx@$1:./
4) ssh.sh - 転送スクリプトを実行させるサブ・スクリプト
#!/bin/bash
ssh adminx@$1 "./auto_poweroff.sh" 
5) chkfile.sh - 実行ファイルが NAS に存在するかを調べるサブ・スクリプト
#!/bin/bash
ssh adminx@$1 "ls ./auto_poweroff.sh"
exit $?
6) 上記 5 つのファイルをホスト Linux 上の同じディレクトリに置き(例では、~/nasctrl/)、chmod 750 としておく. Root である必要はなく、単なる 1 ユーザアカウントで OK.

7) ホスト Linux での crontab -e
NAS の I{P が 192.168.1.91 だった場合の例
*/15 * * * * ./nasctrl/sendscript.sh 192.168.1.91 >> ./nasctrl/nas01.log 2>&1

今回仕掛けた自動 poweroff 機構を簡単に一時停止したい場合の手段として、NAS での ssh session を開いていれば poweroff しない、という細工をしたのだが、poweroff を司るスクリプトの実行自体 NAS への ssh なので、永遠に poweroff しないというおマヌケな自体に陥った。とりあえず、の対策部がなんともイケてない。。。