9

I am trying to write a bash script in a file that would, when run start pinging a host until it becomes available, when the host becomes reachable it runs a command and stops executing, I tried writing one but the script continues pinging until the count ends,

Plus I need to put that process in the background but if I run the script with the dollar ($) sign it still runs in foreground,

#!/bin/bash
ping -c30 -i3 192.168.137.163
if [ $? -eq 0 ]
then /root/scripts/test1.sh
exit 0
else echo “fail”
fi

6 Answers 6

16

I would use this, a simple one-liner:

while ! ping -c1 HOSTNAME &>/dev/null; do echo "Ping Fail - `date`"; done ; echo "Host Found - `date`" ; /root/scripts/test1.sh

Replace HOSTNAME with the host you are trying to ping.


I missed the part about putting it in the background, put that line in a shellscript like so:

#!/bin/sh

while ! ping -c1 $1 &>/dev/null
        do echo "Ping Fail - `date`"
done
echo "Host Found - `date`"
/root/scripts/test1.sh

And to background it you would run it like so:

nohup ./networktest.sh HOSTNAME > /tmp/networktest.out 2>&1 &

Again replace HOSTNAME with the host you are trying to ping. In this approach you are passing the hostname as an argument to the shellscript.

Just as a general warning, if your host stays down, you will have this script continuously pinging in the background until you either kill it or the host is found. So I would keep that in mind when you run this. Because you could end up eating system resources if you forget about this.

2
  • Tnx for the answer and the warning, this is a visualized environment so the script will start after the physical servers boot so the VM's will start certainly, but will keep in mind if i delete a VM, tnx again
    – dusan90
    Commented Feb 12, 2015 at 9:18
  • In particular by logging the failures every time, and storing all the output in a file in /tmp, if the host goes down you'll end up filling /tmp. That tends to be bad news... Commented Feb 13, 2015 at 16:57
7

By passing the parameters '-c 30' to ping, it will try 30 ping and stop. It will check after if the command succeeds. I think it is best to do a loop that contains one ping and check if this ping succeed. Something like that:

while true;
do
  ping -c1 google.com
  if [ $? -eq 0 ]
  then 
    /root/scripts/test1.sh
    exit 0
  fi
done

If by still running on the foreground, you mean it is still printing on the terminal, you can redirect stdin and stdout to /dev/null .

1
  • By unlocking the prompt so i could work on something else, tnx for help
    – dusan90
    Commented Feb 12, 2015 at 9:17
3
ping -oc 100000 Hostname > /dev/null && /root/scripts/test1.sh 
  • ping -o exits the ping after the first packet is received
  • > /dev/null redirects the output, so you won't see it
  • && would run the next command, if the previous command ere successful

In addition, you can run any process in the background by adding & to the end of it; for example, echo "123" & will run in the background

1
  • I seem not to have the -o option Commented Jan 5, 2023 at 8:55
3

An old post, but as a suggestion you can use the -w option on ping to avoid the loop. For example,

ping -w 30 -c 1 host

will try for 30 seconds with one ping per second (default ping has 1 second interval between pings) and will exit on the first successful ping.

If you don't need a timeout, I.e. wait for ever, just use a very large value with -w.

1
  • This failed for me with: "3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2055ms" Commented Jan 21, 2022 at 16:39
2

Here is working modification of your script.

#!/bin/bash
ping -c1 10.1.1.23 > /dev/null
if [ $? -eq 0 ]
  then 
    echo ok 
    exit 0
  else
    echo “fail”
fi

You need to send the output to /dev/null so it won't appear on the screen.

-c is meant for count. If you put -c30, you're going to ping 30 times before your script can move on to the next line. I use -c1 to make the script run faster.

-i is to wait seconds between sending each packet. So -i3 is to wait 3 seconds. I remove -i to make the script run faster.

Last but not least, use indention so that your code looks nice and easier to read.

Sample output

user@linux:~$ ./script.sh 
ok
user@linux:~$

user@linux:~$ ./script.sh 
“fail”
user@linux:~$ 
0
#!/bin/sh

if [ $1 ]
then
for i in ` cat $1`
do
VAR1=$(ping -ac 2 $i| grep -c error)
if [ $VAR1 == "0" ]
then
echo " valid : $i"

else

echo " invalid : $i"

fi

done
else
echo " please present the file name. example: pong /tmp/a "

fi
1
  • 5
    You also might want to add some explaining words...?
    – Thomas
    Commented Jun 1, 2019 at 16:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .