LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Trouble writing ping script (https://www.linuxquestions.org/questions/linux-newbie-8/trouble-writing-ping-script-854867/)

MAW123 01-07-2011 02:27 PM

Trouble writing ping script
 
Hi, I'm trying to write a failover script that accomplishes the following:

Backup server (B) pings main server (A) every 10 minutes, via a crontab entry.

If the ping of A fails, then B tries to ping A again in 120 seconds.

If that second ping from B to A fails, then it waits another 60 seconds, and then, if that one fails, too, it executes another script. If any of the three pings are successful, it is to exit gracefully and wait for crontab to initiate it again.

I based this script off one I found at http://www.cyberciti.biz/tips/simple...d-scripts.html

Code:

#!/bin/bash
#####################################################
#    This script will automatically run every            #
#          ten minutes to see if the main server is                #
#          online or offline. If it is offline, the                #
#          failover mechanism will begin.                                #
#                                                                                                        #
#          Ping looks for failure                                                #
#          If found, sleep 120 ; reping                                        #
#          If found, sleep 60 ; reping                                        #
#          If found after that, execute bringupB.sh                #
#                                                                                                        #
#                                                                                                        #
#####################################################
# add ip / hostname separated by white space
HOSTS="10.10.10.10"
#
# no ping request
COUNT=1
#
# If ping fails, try again in two minutes, and another minute after that
# If all three ping attempts fail, execute the failover script.
#
for myHost in $HOSTS
do
  count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
                sleep 120;
do
  count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
        sleep 60;
do
  count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
        sh /failover/bringupB.sh;
fi
done

However, when the script is executed manually, I get this output:

Code:

'/BpingA_10minutes.sh: line 25: syntax error near unexpected token `do
'/BpingA_10minutes.sh: line 25: `do

This is maddening. Even basic if/else scripts I've found on-line give an error. I understand the concept of scripting, and I've written basic scripts, but this is my first conditional script and I'm stuck.

Please help.

szboardstretcher 01-07-2011 02:32 PM

Code:

for myHost in $HOSTS
do
  count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
                sleep 120;
                count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
                if [ $count -eq 0 ]; then
                      sleep 60;
                      count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
                      if [ $count -eq 0 ]; then
                      sh /failover/bringupB.sh;
                      fi
                fi
  fi
done

Maybe something like this?

MAW123 01-07-2011 02:38 PM

Quote:

Originally Posted by szboardstretcher (Post 4216693)
Maybe something like this?

Thanks for the quick reply, but I get the same syntax error reply:
Code:

'/BpingA_10minutes.sh: line 25: syntax error near unexpected token `do
'/BpingA_10minutes.sh: line 25: `do


szboardstretcher 01-07-2011 02:42 PM

Quote:

HOSTS="10.10.10.10"
#
# no ping request
COUNT=1
#
# If ping fails, try again in two minutes, and another minute after that
# If all three ping attempts fail, execute the failover script.
#
for myHost in $HOSTS; do
count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
sleep 120;
count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
sleep 60;
count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
sh /failover/bringupB.sh;
fi
fi

fi
done
Forgot the semicolon after the For statement and before the Do statement.

MAW123 01-07-2011 02:46 PM

No luck. Similar syntax error:
Code:

'/BpingA_10minutes.sh: line 24: syntax error near unexpected token `do
'/BpingA_10minutes.sh: line 24: `for myHost in $HOSTS; do

FWIW, I'm using CentOS 5.5, and executing this script as root, with this command:
Code:

sh ./BpingA_10minutes.sh

szboardstretcher 01-07-2011 03:30 PM

use /bin/bash, you can't write a script in 'bash' and then use 'sh' to run it.

Quote:

/bin/bash script.sh
or to see the behind the scenes do this:

Quote:

/bin/bash -x script.sh

MAW123 01-07-2011 03:33 PM

You mean, run this command to execute the script?
Code:

/bin/bash ./BpingA_10minutes.sh
No go. Still the same syntax error near unexpected token error.

szboardstretcher 01-07-2011 03:41 PM

Well for what its worth, here is the output from my Centos 5.5 box. It works on Fedora 14 as well. Also, did you copy and paste my recoded version of the script?

Code:

/bin/bash -x test.sh
+ HOSTS=10.10.10.10
+ COUNT=1
+ for myHost in '$HOSTS'
++ ping -c 1 10.10.10.10
++ awk -F, '{ print $2 }'
++ awk '{ print $1 }'
++ grep received
+ count=0
+ '[' 0 -eq 0 ']'
+ sleep 1
++ ping -c 10.10.10.10 10.10.10.10
++ awk -F, '{ print $2 }'
++ awk '{ print $1 }'
++ grep received
+ count=0
+ '[' 0 -eq 0 ']'
+ sleep 1
++ ping -c 10.10.10.10 10.10.10.10
++ awk '{ print $1 }'
++ awk -F, '{ print $2 }'
++ grep received
+ count=0
+ '[' 0 -eq 0 ']'
+ sh /failover/bringupB.sh
sh: /failover/bringupB.sh: No such file or directory

and some version info

Code:

uname -a
Linux servermine 2.6.18-194.17.1.el5 #1 SMP Wed Sep 29 12:50:31 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux

cat /etc/redhat-release
CentOS release 5.5 (Final)

rpm -qa |grep bash
bash-3.2-24.el5


MAW123 01-07-2011 03:47 PM

Thank you so much for your help!

Running the script with +x in the execute command pointed me to encoding problems in the script, so I ran dos2unix on it (I wrote it on my Win7 host.... Grr....) and it seems to work perfectly now.

szboardstretcher 01-07-2011 03:49 PM

Quote:

Originally Posted by MAW123 (Post 4216754)
Thank you so much for your help!

Running the script with +x in the execute command pointed me to encoding problems in the script, so I ran dos2unix on it (I wrote it on my Win7 host.... Grr....) and it seems to work perfectly now.

Glad to help.

Go ahead and click "Yes you found this helpful" on one of these in the bottom right hand corner, to help my reputation go up. Appreciate it. And click [Solved] up top to mark the thread as solved.

Also, on my recoded version, I kept the #!/bin/bash -x in there for troubleshooting, you might want to take that -x out of there.

MAW123 01-12-2011 12:28 PM

One more thing....
 
Thanks for all of your help, I hope you, or someone else, can help me with one last bit.

I'm trying to have the cron job touch a file when everything is okay (in other words, when the ping is successful). I'm trying to do so via the else part of the script, but it doesn't seem to work. Here's my code:
Code:

#!/bin/bash
##############################################
#    This script will automatically run every
#    ten minutes to see if the main server is
#    online or offline. If it is offline, the
#    failover mechanism will begin.
#                                                   
#    Ping looks for failure
#    If found, sleep 120 ; reping
#    If found, sleep 60 ; reping
#    If found after that, execute bringupB.sh
#                                                 
# add ip / hostname separated by white space
HOSTS="10.10.10.10"
#
# no ping request
COUNT=1
#
# If ping fails, try again in two minutes, and another minute after that
# If all three ping attempts fail, execute the failover script.
#
for myHost in $HOSTS; do
count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
/bin/touch /failover/status;
/bin/echo "Uh-oh! The ping failed. Waiting two minutes before we try again..." > /failover/status;
sleep 120;
count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
/bin/echo "Hmm... It's still not responding. Let's wait one more minute before we panic..." >> /failover/status;
sleep 60;
count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
/bin/echo "Oh, noes! It's time to bring this server online!" >> /failover/status;
/bin/bash /failover/bringupB.sh;
else
/bin/touch /failover/checked_ok;
/bin/echo "Everything is okay at:" >> /failover/checked_ok;
/bin/date >> /failover/checked_ok
fi
/bin/touch /failover/checked_ok;
/bin/echo "Everything is okay at:" >> /failover/checked_ok;
/bin/date >> /failover/checked_ok
fi
/bin/touch /failover/checked_ok;
/bin/echo "Everything is okay at:" >> /failover/checked_ok;
/bin/date >> /failover/checked_ok
fi
done

The output, when I run it manually, is:
Code:

[root@backupserver failover]# /bin/bash -x /failover/BpingA_10minutes.sh
+ HOSTS=10.10.10.10
+ COUNT=1
+ for myHost in '$HOSTS'
++ ping -c 1 10.10.10.10
++ grep received
++ awk -F, '{ print $2 }'
++ awk '{ print $1 }'
+ count=1
+ '[' 1 -eq 0 ']'

Touching, and writing the /failover/status file works, when the ping fails, but touching/writing the /failover/checked_ok file does not work when the ping is successful.

Thanks in advance!

MAW123 01-12-2011 12:40 PM

Nevermind, I figured it out.

Code:

#!/bin/bash
##############################################
#    This script will automatically run every
#          ten minutes to see if the main server is
#          online or offline. If it is offline, the
#          failover mechanism will begin.
#                                                   
#          Ping looks for failure
#          If found, sleep 120 ; reping
#          If found, sleep 60 ; reping
#          If found after that, execute bringupB.sh
#                                                 
# add ip / hostname separated by white space
HOSTS="10.10.10.10"
#
# no ping request
COUNT=1
#
# If ping fails, try again in two minutes, and another minute after that
# If all three ping attempts fail, execute the failover script.
#
for myHost in $HOSTS; do
count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
/bin/touch /failover/status;
/bin/echo "Uh-oh! The ping failed. Waiting two minutes before we try again..." > /failover/status;
sleep 120;
count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
/bin/echo "Hmm... It's still not responding. Let's wait one more minute before we panic..." >> /failover/status;
sleep 60;
count=$(ping -c $myHost $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
/bin/echo "Oh, noes! It's time to bring this server online!" >> /failover/status;
/bin/bash /failover/bringupB.sh;
else
/bin/touch /failover/checked_ok;
/bin/echo "Everything is okay at:" >> /failover/checked_ok;
/bin/date >> /failover/checked_ok
fi
else
/bin/touch /failover/checked_ok;
/bin/echo "Everything is okay at:" >> /failover/checked_ok;
/bin/date >> /failover/checked_ok
fi
else
/bin/touch /failover/checked_ok;
/bin/echo "Everything is okay at:" >> /failover/checked_ok;
/bin/date >> /failover/checked_ok
fi
done



All times are GMT -5. The time now is 03:00 AM.