0

First I want to apologize for being an absolute noob at programming, writing scripts, etc. I'm running a FreeNAS Server and a Raspberry Pi which I'd like to include a sh-Script which should check if 8 clients (IP addresses) are online. If yes they should stop but if all IP's are offline, it should perform another task / script.

Here's my problem: On the internet (src: https://www.tech-blogger.net/freenas-automatisch-bei-nicht-benutzung-abschalten/) I found a script which checks specific IP's and if they're offline it should shutdown automatically. When I ping those addresses I get 100% package lost which indicates that they are offline. But the script echos me that at least one client is offline. Because I'm not THAT dumb I assume that it has something to do with my code. Does anyone know what goes wrong with my Script?:

HOST1=192.168.1.32
HOST2=192.168.1.33
HOST3=192.168.1.34
HOST4=192.168.1.35
HOST5=192.168.1.36

_exit () {
case $1 in
1) echo „No Shutdown – At least one PC is online“ ;;
2) echo „No PC is online – Shutdown“ ; shutdown -p now ;;
esac
exit $1;
}

#Check if IPs are online
if [ `ping -c 1 -i 1 $HOST1 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST2 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST3 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST4 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST5 | grep -wc 100.0%` -eq 0 ] ; then _exit 1;

#All Clients are offline, shutdown
else
_exit 2
fi
fi
2
  • if [ $(cmd | grep -c ...) -eq 0 ] is an anti-pattern. Use if ! cmd | grep -q ... instead Commented May 27, 2019 at 17:08
  • 1
    But you shouldn't be using grep at all here. ping will return 0 if it receives a response, non-zero otherwise, so you can just do if ( ping -c 1 -t 1 $HOST1 || ping -c 1 -t 1 $HOST2 || ... ) > /dev/null 2>&1 ; then to see if any host responds. Commented May 27, 2019 at 17:21

2 Answers 2

0

I am not 100 % sure if I get your Problem right. But I think you should try to replace || with && in your if statement.

|| = or && = and

Thus it will only go into the shutdown parts, when all Clients are off.

edit:

ping -c 1 -i 1 192.168.1.36
PING 192.168.1.36 (192.168.1.36) 56(84) bytes of data.
From 62.155.241.85 icmp_seq=1 Destination Host Unreachable

--- 192.168.1.36 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

It's 100% packet loss not 100.0%. Thus you check for something that does not occur.

#!/bin/bash

HOST1=192.168.1.32
HOST2=192.168.1.33
HOST3=192.168.1.34
HOST4=192.168.1.35
HOST5=192.168.1.36

_exit () {
case $1 in
1) echo „No Shutdown – At least one PC is online“ ;;
2) echo „No PC is online – Shutdown“ ;; # shutdown -p now ;;
esac
exit $1;
}

#Check if IPs are online
if [ `ping -c 1 -i 1 $HOST1 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST2 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST3 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST4 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST5 | grep -wc 100%` -eq 0 ] ; then _exit 1;

#All Clients are offline, shutdown
else                                                                                                                                                                                           
_exit 2
fi

This works as expected ( on my machine ). :-)

Sign up to request clarification or add additional context in comments.

1 Comment

Yes this worked fine. Thank you very much for your help :-)
0

As William Pursell said in a comment, when ping doesn't reach the requested IP, it returns a non-zero exit code indicating failure. The if statement in shells like Bash can use that exit code directly without having to use bracketed conditional expressions.

I would recommend a loop instead of a long conditional. This will be easier to read and maintain and scales more readily if the number of hosts change.

# create an array of IPs
host_ips=(
    192.168.1.32
    192.168.1.33
    192.168.1.34
    192.168.1.35
    192.168.1.36
)

for ip in "${host_ips[@]}"
do
    if ping -c 1 -i 1 "$ip"
    then
        _exit 1
        # no need to break since _exit doesn't return
    fi
done
# if we made it this far, none are online
_exit 2

2 Comments

I tried this but my Raspberry tells me there is a syntax error because of the ( in the second line.
@AlphaInc.: You need to make sure you're using Bash and not sh since the former supports arrays and the latter usually doesn't. #!/bin/bash should be the first line in your script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.