Simple Linux and UNIX system monitoring with ping command and scripts

by nixcraft on July 21, 2006 · 30 comments

You can simply monitor your remote system hosted some remote IDC. There may be tons of causes for which system goes out the network.

Understanding ping command

ping is one of the basic and nifty command to test network connection. For example you can send 4 ping request to cyberciti.biz with following command:
$ ping -c 4 cyberciti.biz
$ ping -c 4 router

Output:

PING router (192.168.1.254) 56(84) bytes of data.
64 bytes from router (192.168.1.254): icmp_seq=1 ttl=64 time=1.02 ms
64 bytes from router (192.168.1.254): icmp_seq=2 ttl=64 time=0.824 ms
64 bytes from router (192.168.1.254): icmp_seq=3 ttl=64 time=0.826 ms
64 bytes from router (192.168.1.254): icmp_seq=4 ttl=64 time=0.843 ms
--- router ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3012ms
rtt min/avg/max/mdev = 0.824/0.880/1.027/0.085 ms

Just see output '--- router ping statistics ---', 4 received is key to verify that 4 packets send and received successfully. You can extract 4 received with the following command:
$ ping -c4 router | grep 'received'
Output:

4 packets transmitted, 4 received, 0% packet loss, time 3012ms

Next logical step is to just get number 4 received using awk command:
$ ping -c4 router | grep 'received' | awk -F',' '{ print $4}'
Output:

4 received 

Last step is to just get 4 number and remove received word:
$ ping -c4 router | grep 'received' | awk -F',' '{ print $2}' | awk '{ print $1}'
Output:

4 

Shell script to system monitoring with ping command

Now you know how to obtained received packets, it is time to automate entire process with simple script. Here is sample script (download link):

#!/bin/bash
HOSTS="cyberciti.biz theos.in router"
COUNT=4
for myHost in $HOSTS
do
  count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
    # 100% failed 
    echo "Host : $myHost is down (ping failed) at $(date)"
  fi
done

You can download complete working script which sends an email alert here.

Setup Cron job

In order to run this script every 30 minutes (or as per your requirements), you need to install a script as cron job:
$ chmod +x /path/to/monitorHost
Install the monitorHost script as crontab using the editor:
$ crontab -e
Append the following cronjob entry:
# Monitor remote host every 30 minutes using monitorHost
30 * * * * /home/vivek/bin/monitorHost

Save and close the file.

Featured Articles:

Share this with other sys admins!
Facebook it - Tweet it - Print it -

We're here to help you make the most of sysadmin work. So, subscribe!

{ 30 comments… read them below or add one }

1 kotnik July 24, 2006

This is the script I’m using for the same thing:

case `ping -qnc 1 google.com 2>&1` in
*’100% packet loss’*)
echo “The network is DOWN.”
exit 1
;;
esac

One way or around…

Reply

2 randomz July 24, 2006

Nice, though I think a ( got dropped before *’100% packet loss’*) ?

Reply

3 kotnik July 27, 2006

No, ( is not missing. Try it:

http://pastebin.ca/102156

Reply

4 nixcraft July 27, 2006

Kotnik,

Short and sweet code :D

Reply

5 Max June 9, 2007

Hie
this is an ingenious script:)
thanks to share it
I have just a little question.
I didn’t find “Email ID”
can you help me to find it please??

thanks for your help

Reply

6 vivek June 10, 2007

Go here

HTH

Reply

7 TonyK June 11, 2007

You can skip the awk stuff by using cut like this:
ping -c4 localhost | grep ‘received’ | cut -f2 -d’,’ |cut -f2 -d’ ‘

it also returns 4

Reply

8 vivek June 11, 2007

TonyK

Yes you can always use another set of commands to do the same thing. Coding is like that… heh

Appreciate your post!

Reply

9 BenV July 17, 2007

I commonly use this. Just another way to do it.
if [[ $(ping -q -c 3 10.1.1.1) == @(*100% packet loss*) ]]; then
echo “$host is down”
else
echo “$host is alive”
fi

Reply

10 John Golini August 11, 2008

can someone show me a script I could cron every 15 min or so, that would email ‘root’ each time a computer comes up on the LAN or goes off the LAN, giving the ip address and the windows computer name?

Reply

11 Saurabh November 17, 2008

Short and sweet code Benv

Reply

12 ishfaq February 20, 2010

nice script but any tell how to paste the out put on apache page

Reply

13 Amza Marian May 13, 2010

@ishfaq :

echo “Host : $myHost is down (ping failed) at $(date)” >> /var/www/network.txt

Reply

14 Ernest June 17, 2010

@BenV – Will your script work if $host does not exist? Typo’s happen.

Will adding a ‘ping -c1 -w1″ enable a timeout and avoid hanging indefinitely? or is the -w not used that way?

Reply

15 difa December 13, 2010

nice..
thanks you ^,^

Reply

16 Bob Watson February 9, 2011

Along a slightly different vein- I’ve got my e-mail client set to start as soon as I log in, which is often before the network is online. It then tells me it can’t find the server and decides to work off-line. This is annoying, so I added a slight modification of the above at the head of its initialisation script:

while :
do
count=$(ping -c 1 imap.1and1.co.uk | grep ‘received’ | awk -F’,’ ‘{ print $2 }’ | awk ‘{ print $1 }’)
if [ $count -eq 1 ]; then
break
fi
sleep 5
done

Reply

17 HTF April 3, 2011

Quick question:
If I set the ping count to 4 and only one of four will failed will I get the true positive alarm anyway?

Reply

18 Amza Marian April 3, 2011

HTF: Yes

if [ $count -eq 0 ]; then <- only if 100% failed.

Reply

19 Peter April 7, 2011

It works fine except i tried to use it to make sure my internet connection was still up and if the internet connection fails It can’t resolve the host so it can’t try ping to ping it. How could i add a check for this situation?

Reply

20 Vivek Gite April 7, 2011

Check dns settings in /etc/resolv.conf file including firewall settings.

Reply

21 shilpa April 19, 2011

how to check server is alive using ping command at client in unix system programming using ICMP protocol

Reply

22 Amza Marian April 19, 2011

@shilpa: PING using icmp protocol. You can read more here:
http://www.iana.org/assignments/icmp-parameters

Reply

23 shilpa April 22, 2011

have to implement ping command using raw socket in unix

Reply

24 shilpa April 22, 2011

hi,
i am doing a small program on the working of ping command in linux using icmp protocol. here is the code but its giving an error at getuid()

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
char dst_addr[20];
char src_addr[20];
unsigned short in_cksum(unsigned short*,int);
void parse_argvs(char**,char*,char*);
void usage();
char *getip();
char *toip(char*);
int main(int argc, char *argv[])
{
struct iphdr *ip;
struct iphdr *ip_reply;
struct icmphdr *icmp;
struct sockaddr_in connection;
char *packet=NULL;
char *buffer=NULL;
int sockfd;
int optval;
int addrlen;
int siz;
printf(“%d”,getuid());
if(getuid()!=0)
{
fprintf(stderr,”%s:rot privileges needed\n”,*(argv+0));
exit(EXIT_FAILURE);
}
parse_argvs(argv,dst_addr,src_addr);
strncpy(dst_addr,toip(dst_addr),20);
strncpy(src_addr,toip(src_addr),20);
printf(“src addr is %s\n”,src_addr);
printf(“dest addre is %s\n”,dst_addr);
packet=malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
buffer=malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
ip=(struct iphdr *)packet;
icmp=(struct icmphdr *)(packet + sizeof(struct iphdr));
ip->ihl=5;
ip->version=4;
ip->tos=0;
ip->tot_len=sizeof(struct iphdr) + sizeof(struct icmphdr);
ip->id=htons(0);
ip->frag_off=0;
ip->ttl=64;
ip->protocol=IPPROTO_ICMP;
ip->saddr=inet_addr(src_addr);
ip->daddr=inet_addr(dst_addr);
ip->check=in_cksum((unsigned short *)ip,sizeof(struct iphdr));
if((sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))==-1)
{
perror(“socket”);
exit(EXIT_FAILURE);
}
setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int));
icmp->type=ICMP_ECHO;
icmp->code=0;
icmp->un.echo.id=random();
icmp->un.echo.sequence=0;
icmp->checksum=in_cksum((unsigned short *)icmp,sizeof(struct icmphdr));
connection.sin_family=AF_INET;
connection.sin_addr.s_addr=inet_addr(dst_addr);
sendto(sockfd,packet,ip->tot_len,0,(struct sockaddr *)&connection,sizeof(struct sockaddr));
printf(“sent %d byte packet to %s\n”,ip->tot_len,dst_addr);
addrlen=sizeof(connection);
if((siz=recvfrom(sockfd,buffer,sizeof(struct iphdr) + sizeof(struct icmphdr),0,(struct sockaddr *)&connection,&addrlen))==-1)
{
perror(“recv”);
}
else
{
printf(“received %d byte reply from %s\n”,siz,dst_addr);
ip_reply=(struct iphdr *)buffer;
printf(“ID: %d\n”,ntohs(ip_reply->id));
printf(“ttl:%d\n”,ip_reply->ttl);
}
free(packet);
free(buffer);
close(sockfd);
return 0;
}

void parse_argvs(char **argv,char *dst,char *src)
{
int i;
if(!(*(argv + 1 ) ) )
{
usage();
exit(EXIT_FAILURE);
}
if(*(argv + 1) && (!(*(argv + 2 ) ) ) )
{
strncpy(dst,*(argv + 1),15);
return;
}
else if((*(argv + 1 ) && (* ( argv + 2 ) ) ) )
{
strncpy(dst,*(argv + 1 ),15);
i=2;
while(*(argv + i + 1 ) )
{
if(strncmp(*(argv + i),”-s”,2)==0)
{
strncpy(src,*(argv + i + 1),15);
break;
}
i++;
}
}
}

void usage()
{
fprintf(stderr, “\n usage:ping [destination] \n”);
fprintf(stderr,”destination must be provided\n”);
fprintf(stderr,”source is optional \n \n”);
}
char * getup()
{
char buffer[256];
struct hostent *h;
gethostname(buffer,256);
h=gethostbyname(buffer);
return inet_ntoa(*(struct in_addr *)h->h_addr);
}
char * toip(char * address)
{
struct hostent *h;
h=gethostbyname(address);
return inet_ntoa(*(struct in_addr *)h->h_addr);
}
unsigned short in_cksum(unsigned short *addr, int len)
{
register int sum=0;
u_short answer=0;
register u_short *w=addr;
register int nleft=len;
while(nleft > 1)
{
sum+=*w++;
nleft-=2;
}
if(nleft==1)
{
*(u_char*) (&answer)=*(u_char*)w;
sum+=answer;
}
sum=(sum>>16) + (sum & 0xffff);
sum+=(sum>>16);
answer=~sum;
return(answer);
}

Reply

25 shilpa April 22, 2011

can anybody suggest me a solution plz

Reply

26 Henrik C July 8, 2011

Hi coders

What would i use if i needed 1 timestamp when “Ping up again” ?

Thanks

Reply

27 YC July 20, 2011

This is a great tutorial but there is a little problem. Your cron job won’t be executed every 30 minutes but instead 1 time per hour at 30 minute (1:30, 2:30, 3:30). To run it every 30 min, you should change the first parameter to */30.

Reply

28 blognadei October 24, 2011

thanks , this work :D

Reply

29 Константин Кръстев November 23, 2011

ping -qnc 2 google.com > /dev/null 2>&1 && echo ‘Host up!’ || echo ‘Host down!’

Reply

30 Der December 4, 2011

@Константин Кръстев
I love your line, but could you explain the bit after the “>” I don’t get that.

It does work I just don’t know why!

Thanks,
Der

Reply

Leave a Comment

You can use these HTML tags and attributes for your code and commands: <strong> <em> <ol> <li> <u> <ul> <blockquote> <pre> <a href="" title="">




Previous post:

Next post: