Automatic shutdown based on IOT event

Don't miss a thing. Post your questions and discussion about other uncategorized NAS features here.
Post Reply
Arsath
New here
Posts: 2
Joined: Thu Jul 28, 2022 1:51 am

Automatic shutdown based on IOT event

Post by Arsath » Wed Aug 03, 2022 11:34 pm

I've been experiencing constant power cuts due to load shedding where I live, my QNAP TS451+ is on a UPS , but not a smart UPS, I wrote a script that runs as a CRON job that detects a power outage and initiates a controlled shutdown.
So far it has worked perfectly, all I am doing is sending a few packets of data to SonOff switch to check if its alive, it is ideal for me to do this as SonOff devices boot up in approximately 3 seconds, so any power flickers (that happens too during storms), it recovers fast.
My question is what can I improve on this ? (Dont have the budget a for smart UPS at the moment).
And also when write to the log the power off event, it rights multiple times, even when I do a scheduled power off the log write and power off events get triggered in the script , I think this is due to network service is shutdown first and the ping fails.

Any suggestions to improve this is welcome!

Here is the code.

Code: Select all

#/usr/bin/bash
s_run=1
ext_code=0
count=0

while [ $ext_code -eq 0 ]
do

        ext_code=$(ping -c 5 172.24.1.207 > /dev/null ; echo $?)
        #echo $ext_code

        if [ $ext_code -eq 1 ]
        then
                /sbin/log_tool -a "Power failure detected, shutting down in 15 seconds if it persists" -N  "PowerOut CRON" -t 0 
        fi

        if [ $ext_code -eq 1 ] && [ $count != 5 ]
        then
                while [ $count != 5 ]
                do
                        sleep 1
                        ext_code=$(ping -c 2 172.24.1.207 > /dev/null ; echo $?)
                        count=$((count+1))
                        echo "try " + $count
                        if [ $ext_code -eq 0 ]
                        then
                               /sbin/log_tool -a "Power Restored" -N  "PowerOut CRON" -t 0 
                                count=0
                                break
                        fi
                done
                if [ $ext_code -eq 1 ]

                then

                      /sbin/log_tool -a "Controlled power off initiated due to power failiure" -N  "PowerOut CRON" -t 1  
                        poweroff


                fi

        fi

done

here is my CRON TAB entry

Code: Select all

* * * * * /share/CACHEDEV1_DATA/homes/admin/powerout/powerout.sh

User avatar
OneCD
Guru
Posts: 10301
Joined: Sun Aug 21, 2016 10:48 am
Location: "... there, behind that sofa!"

Re: Automatic shutdown based on IOT event

Post by OneCD » Fri Aug 05, 2022 12:39 pm

Hi and welcome to the forum. :)

If I may offer a few observations...
  • Your present hashbang line is:

    Code: Select all

    #/usr/bin/bash
    ... which should probably be:

    Code: Select all

    #!/usr/bin/bash
    ... or the more modern:

    Code: Select all

    #!/usr/bin/env bash
  • When running a script via a crontab entry, ensure your script starts by confirming it is the only copy running (create a lockfile on start, and remove it on exit). This way, you prevent overruns (a second copy being executed at the next matched minute while the first copy is still executing).
  • If you're testing the exit code for 'ping' (and pretty-much anything else), it's usually more foolproof to test for non-zero instead of 1, like:

    Code: Select all

    if [[ $ext_code -ne 0 ]]
    This way, your conditionals will fire on anything returned by 'ping' that isn't a success.
  • Advanced-beginner tip:

    Code: Select all

    count=$((count+1))
    ... can be reduced to:

    Code: Select all

    ((count++))
    Both will increment $count by 1.
  • Code: Select all

    while [ $count != 5 ]
    Typical coding conventions when testing accumulators are to either test the low-side for less-than-and-equals the target, or test the high-side with equals-target-and-greater. Testing only for a specific target value in a loop can bite you if your accumulator changes value (and skips the target), which then means your loop becomes endless.
  • Also, in the example above, you're performing a string comparison, not an arithmetic comparison. Try using -lt, -gt, -le, -ge, -eq, -ne when testing numeric values.
  • You're using single tests '[' where double tests '[[' are typically specified. In QTS, this doesn't matter as they're all effectively converted to double tests anyway, but it's something to be aware-of.
  • To prevent your code continuing to run during the 'poweroff' sequence, include a flagfile in /var/run/ or a similar non-persistent location, and ensure your script won't run if it sees that flagfile (same idea as mentioned earlier regarding the lockfile). Then ensure your script creates this same flagfile just before issuing the 'poweroff' command.
  • Lastly, when pasting your code online, using 4 spaces as tabs makes it much easier to read in code blocks. ;)

ImageImageImageImageImageImageImageImageImageImageImageImageImageImageImageImageImageImage

Arsath
New here
Posts: 2
Joined: Thu Jul 28, 2022 1:51 am

Re: Automatic shutdown based on IOT event

Post by Arsath » Fri Aug 05, 2022 10:57 pm

Hi,

Thanks for the reply,
I have improved the code, but I still see two processes running for powerout.sh

Code: Select all

#!/usr/bin/bash
if { set -C; 2>/dev/null >~/manlock.lock; }; then
   trap "rm -f ~/manlock.lock" EXIT
else
   echo "Lock file exists�~@� exiting"
   exit
fi


ext_code=0
count=0

while [ $ext_code -eq 0 ]
do
    ext_code=$(ping -c 5 172.24.1.207 &> /dev/null ; echo $?)

    if [ $ext_code -eq 1 ]
        then
                /sbin/log_tool -a "Power failure detected, shutting down in 15 seconds if it persists" -N  "PowerOut CRON" -t 0 
    fi

    if [ $ext_code -eq 1 ] && [ $count -ne 5 ]
        then
                while [ $count -ne 5 ]
                do
                        sleep 1
                        ext_code=$(ping -c 2 172.24.1.207 &> /dev/null ; echo $?)
                        
                        ((count++))

                        echo "try " + $count
                        if [ $ext_code -eq 0 ]
                        then
                               /sbin/log_tool -a "Power Restored" -N  "PowerOut CRON" -t 0 
                                count=0
                                break
                        fi
                done
                if [ $ext_code -eq 1 ]

                then

                      /sbin/log_tool -a "Controlled power off initiated due to power failiure" -N  "PowerOut CRON" -t 1  
                        poweroff


                fi
    fi

done

User avatar
OneCD
Guru
Posts: 10301
Joined: Sun Aug 21, 2016 10:48 am
Location: "... there, behind that sofa!"

Re: Automatic shutdown based on IOT event

Post by OneCD » Sat Aug 06, 2022 3:50 am

Arsath wrote:
Fri Aug 05, 2022 10:57 pm
I have improved the code, but I still see two processes running for powerout.sh
It looks like you've made about half of the changes I suggested, and included what appears to be copypaste code. Be careful when doing this, as it introduces new problems - for example, the use of ~ (home) in the cron environment isn't a good idea as cron typically operates in its own environment with its own variables. It's much safer to use absolute paths when dealing with cron.

Maybe make a few more mods and see how it looks then? ;)

ImageImageImageImageImageImageImageImageImageImageImageImageImageImageImageImageImageImage

Post Reply

Return to “Miscellaneous”