I want to write a script, that would keep checking if any of the devices in network, that should be online all day long, are really online. I tried to use ping, but
if [ "`ping -c 1 some_ip_here`" ] then echo 1 else echo 0 fi gives 1 no matter if I enter valid or invalid ip address. How can I check if a specific address (or better any of devices from list of ip addresses) went offline?
11 Answers
Ping returns different exit codes depending on the type of error.
ping 256.256.256.256 ; echo $? # 68 ping -c 1 127.0.0.1 ; echo $? # 0 ping -c 1 192.168.1.5 ; echo $? # 2 0 means host reachable
2 means unreachable
4You don't need the backticks in the if statement. You can use this check
if ping -c 1 some_ip_here &> /dev/null then echo 1 else echo 0 fi The if command checks the exit code of the following command (the ping). If the exit code is zero (which means that the command exited successfully) the then block will be executed. If it return a non-zero exit code, then the else block will be executed.
2I can think of a one liner like this to run
ping -c 1 127.0.0.1 &> /dev/null && echo success || echo fail Replace 127.0.0.1 with IP or hostname, replace echo commands with what needs to be done in either case.
Code above will succeed, maybe try with an IP or hostname you know that is not accessible.
Like this:
ping -c 1 google.com &> /dev/null && echo success || echo fail and this
ping -c 1 lolcatz.ninja &> /dev/null && echo success || echo fail 1There is advanced version of ping - "fping", which gives possibility to define the timeout in milliseconds.
#!/bin/bash IP='192.168.1.1' fping -c1 -t300 $IP 2>/dev/null 1>/dev/null if [ "$?" = 0 ] then echo "Host found" else echo "Host not found" fi 6This is a complete bash script which pings target every 5 seconds and logs errors to a file.
Enjoy!
#!/bin/bash FILE=errors.txt TARGET=192.168.0.1 touch $FILE while true; do DATE=$(date '+%d/%m/%Y %H:%M:%S') ping -c 1 $TARGET &> /dev/null if [[ $? -ne 0 ]]; then echo "ERROR "$DATE echo $DATE >> $FILE else echo "OK "$DATE fi sleep 5 done FYI, I just did some test using the method above and if we use multi ping (10 requests)
ping -c10 8.8.8.8 &> /dev/null ; echo $?
the result of multi ping command will be "0" if at least one of ping result reachable, and "1" in case where all ping requests are unreachable.
1up=`fping -r 1 $1 ` if [ -z "${up}" ]; then printf "Host $1 not responding to ping \n" else printf "Host $1 responding to ping \n" fi for i in `cat Hostlist` do ping -c1 -w2 $i | grep "PING" | awk '{print $2,$3}' done This seems to work moderately well in a terminal emulator window. It loops until there's a connection then stops.
#!/bin/bash # ping in a loop until the net is up declare -i s=0 declare -i m=0 while ! ping -c1 -w2 8.8.8.8 &> /dev/null ; do echo "down" $m:$s sleep 10 s=s+10 if test $s -ge 60; then s=0 m=m+1; fi done echo -e "--------->> UP! (connect a speaker) <<--------" \\a The \a at the end is trying to get a bel char on connect. I've been trying to do this in LXDE/lxpanel but everything halts until I have a network connection again. Having a time started out as a progress indicator because if you look at a window with just "down" on every line you can't even tell it's moving.
I liked the idea of checking a list like:
for i in `cat Hostlist` do ping -c1 -w2 $i | grep "PING" | awk '{print $2,$3}' done but that snippet doesn't care if a host is unreachable, so is not a great answer IMHO.
I ran with it and wrote
for i in `cat Hostlist` do ping -c1 -w2 $i >/dev/null 2>&1 ; echo $i $? done And I can then handle each accordingly.
2check host every one second and send message when host is reach
while :;do ping -c 1 -w 1 -q 8.8.8.8 &>/dev/null && /root/telegram-send.sh "Host reacheble now" && break || sleep 1;done