I'm trying to create a script for seeing if a host is alive, and depending on the ammount of packet loss, send an mail+sms to warn if the host seems to be dead.
The script i'm trying to use is:
pinger ()
{
ping_stat=`ping -c 4 host.name | grep loss | awk '{print $7}'`
echo "Packet loss reported = $ping_stat"
test_
}
test_ ()
{
if [[ $ping_stat < 25% ]]
then
if [[ $ping_count < 2 ]]
then
let ping_count=ping_count+1
echo "More than 25% packet loss! I will take a nap for 2 minutes and then try again before I determine wether or not the host is down!"
sleep 120
echo "Trying again! Ping_count is $ping_count."
pinger
else
echo "The host host.name does not respond to ping or is heavily loaded with traffic. Packet loss is $ping_stat. Please investigate ASAP!"
fi
else
echo "Host is responding well!"
fi
}
for _switch ; do
case $_switch in
-remote)
ping_count=1
pinger
;;
-boot)
sleep 90
get_ip=`ifconfig em0 | grep inet | awk '{print $2'}`
get_hostname=`uname -n`
message="$get_hostname has just (re)booted. (new) IP is $get_ip"
sms=`echo $message | sed 's/ /+/g'`
# code for sending sms goes here!
echo $message > /tmp/ip_mail.txt
mail -s "$get_hostname" mail@he.re < /tmp/ip_mail.txt
rm /tmp/ip_mail.txt
;;
esac
No matter if packet loss reported is 0 or 100%, the script reports the host as dead.
Strip off the percent sign. The shell can't calculate with this - it doesn't know what % is in terms of arithmetics, ie. write a plain 25.
So in the line
add something like
| sed 's/%//g'
To strip off the percent symbol there too.
2. When doing arithmetics, I would use (( and )) instread of [[ and ]].
See the man page for your shell for details. (( )) is used for arithmetic evaluation so is more suited to calculations and numeric comparisons. [[ ]] is used for conditional expressions, which includes some numeric stuff but is also useful for matching strings, testing for the presence of files, directories, and other types of devices, etc. If you were to use [[ ]] the syntax would be:
Thanks for your help, it means a lot to me in my learning.
Now I'm stuck again, and i don't know how to solve this problem. =(
I want to put the hostname as a agument when running the script. Like:
script.sh -remote host.name
In this case, the hostname would be $2, but, when i do
ping_stat=`ping -c 4 $2 | grep loss | awk '{print $7}' | sed 's/%//g'`
it fails.
It seems that using $2 inside the variable doesn't work...
Can anyone please explain to me why it doesn't work, and how to get what i want to work?
I've been trying for some hours now, but I can't find any sollution, nor an answer to why it doesn't work. =(
ping_stat=`ping -c 4 $2 | grep loss | awk '{print $7}' |cut -d % -f1`
ping will take $2 there is no problem i guess please paste what error you are getting??
#! /usr/local/bin/bash
pinger ()
{
ping_stat=`ping -c 4 host.name | grep loss | awk '{print $7}' | sed 's/%//g'`
echo "Packet loss reported = $ping_stat"
test_
}
test_ ()
{
if (( $ping_stat > 25 ))
then
if (( $ping_count < 2 ))
then
let ping_count=ping_count+1
echo "More than 25% packet loss! I will take a nap in 2 minutes and then try again before i determine if host is down!"
sleep 120
echo "Trying again! Ping_count is $ping_count."
pinger
else
echo "The host $2 does not respond to ping. Please investigate ASAP!"
touch /tmp/no.notify.beacon
looper
fi
else
echo "Host is responding!"
fi
}
looper ()
{
ping_stat_loop=`ping -c 4 host.name | grep loss | awk '{print $7}' | sed 's/%//g'`
echo "Packet loss reported = $ping_stat"
if (( $ping_stat_loop > 75 ))
then
echo "Host still down. Trying again in 60 seconds..."
sleep 60
looper
else
echo "0% packet loss! Host is alive!"
rm -rf /tmp/no.notify.beacon
fi
}
for _switch ; do
case $_switch in
-remote)
if [ -e /tmp/no.notify ]
then
exit 0
else
ping_count=1
pinger ;;
fi
-boot)
sleep 90
get_ip=`ifconfig em0 | grep inet | awk '{print $2'}`
get_hostname=`uname -n`
message="$get_hostname has just (re)booted. (new) IP is $get_ip"
sms=`echo $message | sed 's/ /+/g'`
echo $message > /tmp/ip_mail.txt
mail -s "$get_hostname" mail@he.re < /tmp/ip_mail.txt
rm -rf /tmp/ip_mail.txt
echo $sms
;;
esac
done
exit 0
And, if i change host.name to $2, this is what i get...
i mean to say "(("=test="[" these three are equal you can use any of these with if..
and try to run your script sh -x ./scriptname -remote host.name you will get an idea where exactly you are going wrong
I stopped the script with ctrl+c, since it would otherwise get stuck in an infinite loop.
Damn, this is really getting annoying...
Just to test it, inside the case, in the -remote part, i added:
echo $2
exit 0
before setting the ping_count..
And guess what, it echoed the hostname as it should.. so why doesn't $2 work in the rest of the code? *argh*
oh man got your problem...
in your script ping is inside the pinger() function right are you passing any arguments to it?? no right??
so where ever you call pinger type pinger $2
hope it works...
Uhm... just.. one more thing.. =(
I get the same problem after the 120 second sleep...
I change that to
sleep 120
echo "Trying again! Ping_count is $ping_count."
pinger $2
So now i'm back to square one.. =(
It take the $2 argument the first time, but not the second.. and I don't have a clue why..
And I'd guess, since this doesn't work, I guess that looper $2 won't work either... =(
I get the same information with sh -x as last time..
Any suggestions?
simple!!!
when you pass the argument to script first time
include var=$2 imean store $2 in some variable
then pass $var as a argument to pinger after sleep
it should work