≡ Menu

Shell Script To Monitor Services Such As Web / Http, Ssh, Mail Server

#!/bin/bash
# Shell script to monitor running services such as web/http, ssh, mail etc.
# If service fails it will send an Email to ADMIN user
# -------------------------------------------------------------------------
# Copyright (c) 2006 nixCraft project 
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# ----------------------------------------------------------------------
# See URL for more info
# http://www.cyberciti.biz/tips/processing-the-delimited-files-using-cut-and-awk.html
# ---------------------------------------------------
# Last updated: Jun - 15 - 2009.
ports="22 53 80 25"
# service names as per above ports
service="SSH DNS WEB MAIL"
#Email id to send alert
ADMINEMAIL="admin@myispname.com"
#Bin paths, set them according to your Linux distro
NETSTAT=/bin/netstat
MAIL=/usr/bin/mail
LOGGER=/usr/bin/logger
ID=/usr/bin/id
# Red hat usr uncomment
MAIL=/bin/mail
LOGGER=/bin/logger
#Counters, set defaults
c=1
status=""
sendmail=0
# set the following to 1, if you want message in /var/log/messages via a SYSLOG
logtosyslog=0
# Log file used to send an email
LOG="/tmp/services.log.$$"
# log message to screen and a log file
log(){
	echo "$@"
	echo "$@" >> $LOG
}
# log message and stop script
die(){
	echo "$@"
	exit 999
}
# Make sure only root can run it
is_root(){
	local id=$($ID -u)
	[ $id -ne 0 ]  && die "You must be root to run $0."
}
# Look out for all bins and create a log file
init_script(){
	[ ! -x $MAIL ] && die "$MAIL command not found."
	[ ! -x $NETSTAT ] && die "$NETSTAT command not found."
	[ ! -x $LOGGER ] && die "$LOGGER command not found."
	[ ! -x $ID ] && die "$ID command not found."
	is_root
	>$LOG
}
# check for all running services and shoot an email if service is not running
chk_services(){
	log "-------------------------------------------------------------"
	log "Running services status @ $(hostname) [ $(date) ]"
	log "-------------------------------------------------------------"
	# get open ports
	RPORTS=$($NETSTAT -tulpn -A inet | grep -vE '^Active|Proto' | grep 'LISTEN' | awk '{ print $4}' | cut -d: -f2 | sed '/^$/d' | sort  -u)
	# okay let us compare them
	for t in $ports
	do
		sname=$(echo $service | cut -d' ' -f$c)
		echo -en " $sname\t\t\t : "
		echo -en " $sname\t\t\t : " >> $LOG
		for r in $RPORTS
		do
			if [ "$r" == "$t" ]
			then
				status="YES"
				sendmail=1
				break
			fi
		done
		echo -n "$status"
		echo ""
		echo -n "$status" >>$LOG
		echo "" >>$LOG
		# Log to a syslog /var/log/messages?
		# This is useful if you have a dedicated syslog server
		[ $logtosyslog -eq 1  ] && $LOGGER "$sname service running : $status"
		# Update counters for next round
		c=$( expr $c + 1 )
		status="NO"
	done
	log "-------------------------------------------------------------"
	log "This is an automatically generated $(uname) service status notification by $0 script."
	if [ $sendmail -eq 1 ];
	then
		$MAIL -s "Service Down @ $(hostname)" $ADMINEMAIL < $LOG
	fi
}
### main ###
init_script
chk_services
### remove a log file ###
[ -f $LOG ] && /bin/rm -f $LOG
{ 33 comments… add one }
  • Amar September 11, 2012, 3:13 am

    Will this work to check for any webservices exposed by a server.

  • Amar September 11, 2012, 3:11 am

    Hi,

    Can we check through shell script if certain web service are up or not ?

    Regards,
    Amar Sharma

  • Michael Pivonka April 12, 2012, 7:36 am

    Had problem with httpd not using a set ip and with the command in script above does not find services that don’t have them attached to an ip. So I have fixed this with the following command.

    NETSTAT -tulpn | grep -vE '^Active|Proto' | grep 'LISTEN' | awk '{ print $4}' | awk -F: '{print $NF}' | sed '/^$/d' | sort -u
    
  • Aneesh July 12, 2011, 5:31 pm

    On .el5 this is not working . Only SMTP status printed properly.

  • MuaDDip October 17, 2010, 7:26 am

    RPORTS=$($NETSTAT -tulpn | grep -vE ‘^Active|Proto’ | grep ‘LISTEN’ | awk ‘{ print $4}’ | sed ‘s/[0-9a-z\.\:]*\:\([0-9]\+\)$/\1/’ | sort -u)

  • Brian October 10, 2010, 4:33 pm

    Hi,
    You have a couple of bugs.
    1. The script sends whenever at least one process is UP, you want the opposite.
    2 You need to set status to ‘NO’ at the beginning of the loop rather than the end, otherwise if the first service is down it will have a status of empty string.
    3. I would recommend using variables more descriptive than a single character, it will make it easier to read.

    Here are the changes you need to make (note that I renamed the c variable to ‘count’):

    # okay let us compare them
    for t in $ports
    do
    status=”NO”
    sname=$(echo $service | cut -d’ ‘ -f$count)
    echo -en ” $sname\t\t\t : ”
    echo -en ” $sname\t\t\t : ” >> $LOG
    for r in $RPORTS
    do
    if [ “$r” == “$t” ]
    then
    status=”YES”
    break
    fi
    done
    if [ “$status” == “NO” ]
    then
    sendmail=1
    fi
    echo -n “$status”
    echo “”
    echo -n “$status” >>$LOG
    echo “” >>$LOG
    # Log to a syslog /var/log/messages?
    # This is useful if you have a dedicated syslog server
    [ $logtosyslog -eq 1 ] && $LOGGER “$sname service running : $status”

    # Update counters for next round
    count=$( expr $count + 1 )
    done

    • Brian October 10, 2010, 4:35 pm

      Whoops forgot to use the code blocks


      # okay let us compare them
      for t in $ports
      do
      status="NO"
      sname=$(echo $service | cut -d' ' -f$count)
      echo -en " $sname\t\t\t : "
      echo -en " $sname\t\t\t : " >> $LOG
      for r in $RPORTS
      do
      if [ "$r" == "$t" ]
      then
      status="YES"
      break
      fi
      done
      if [ "$status" == "NO" ]
      then
      sendmail=1
      fi
      echo -n "$status"
      echo ""
      echo -n "$status" >>$LOG
      echo "" >>$LOG
      # Log to a syslog /var/log/messages?
      # This is useful if you have a dedicated syslog server
      [ $logtosyslog -eq 1 ] && $LOGGER "$sname service running : $status"

      # Update counters for next round
      count=$( expr $count + 1 )
      done

  • Shaiju August 26, 2010, 10:19 am

    Hi Smeven,
    Thanks a lot…its worked Fine…:)
    We want ot chane #get open ports section to
    RPORTS=$($NETSTAT -tulapn -A inet,inet6 | grep -vE ‘^Active|Proto’ | grep ‘LISTEN’ | awk ‘{ print $4}’ | cut -d: -f2,4 | cut -d: -f2 | sed ‘/^$/d’ | sort -u) .Then only it will works on Ipv6..

    Regards,
    Shaiju

  • smeven July 14, 2010, 3:18 pm

    My experience is that if a port of a running service dosn’t show up in the netstat line, it’s because it’s not using the protocol inet, but inet6 istead.
    try netstat -tulpn -A inet,inet6 , but the some modifications to the cut part of this line has to be done also.
    cut -d: -f2 would fail because of the format of inet6 is different , try cut -d: -f2,4 | cut -d: -f2 instead.

  • Jesse April 9, 2010, 10:51 pm

    It’s emailing me even when all services are up:

    $ sudo ./monitor.sh
    ————————————————————-
    Running services status @ sabresboard [ Fri Apr 9 18:50:43 EDT 2010 ]
    ————————————————————-
    SSH : YES
    WEB : YES
    MAIL : YES
    ————————————————————-
    This is an automatically generated Linux service status notification by ./monitor.sh script

    Still sends me an email.

  • shaiju March 22, 2010, 7:12 am

    Hi thanks for the script..
    How to monitor a new port using the scrip.i want to monitor 8080,and i changed port in the ports=”22 53 80 8080″
    when running the script it is showing that
    SSH : YES
    DNS : YES
    WEB : YES
    tomcat : NO
    please help me
    Regards
    Shaiju

  • Naleen November 18, 2009, 7:45 pm

    This script worked first time for me, no probs at all.
    no modification needed apart from email address, very nice !!!!

  • Jonas Holmgren October 7, 2009, 11:03 am

    Note that due to the SLQ Injection protection in this forum, the opening apostrophes were replaced with back-quotes. What you see on the screen is correct, but you can’t copy and paste it into your script.

    • Vivek Gite October 14, 2009, 6:26 am

      You can always download script file.

  • Jonas Holmgren October 7, 2009, 10:47 am

    Try with

    RPORTS="`nmap -sT $(ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | cut -f2 -d: | awk '{ print $1}') 2>/dev/null | awk '/^[0-9]/ {print $1}' | cut -f1 -d/`"

    Regards,
    Jonas

  • Fernando Hallberg October 2, 2009, 9:39 pm

    Hi,

    This script sendmail at services is UP, and not if one of services is DOWN! :D

    I remove the send mail lines and create a external check for a NO ocurrence, and if exists send mail for the administrators and restart services :D

    Regards,

    Fernando

  • FarhanFaisal October 1, 2009, 3:32 am

    I got the same problem and I’m on FreeBSD. I modified the netstat command part, changed to this.

    RPORTS=$($NETSTAT -ant -A inet | grep ‘LISTEN’ | awk ‘{ print $5}’ | cut -d’.’ -f2 | sed ‘/^$/d’ | sort -u)

    But I still got problem, because of different way those services were initiated. My DNS configured to listen on specific address. So, DNS entry in netstat will be
    XXX.XXX.XXX.XXX.53
    but some other service like smtp will have
    *.25

    I still prefer a script that can monitor the port itself, checking whether its open or not.

  • Smile4u July 14, 2009, 7:07 am

    There is an error in the “init_script”-section:
    [ ! -x $NETSTAT ] && die “$MAIL command not found.”
    should be like this
    [ ! -x $NETSTAT ] && die “$NETSTAT command not found.”

    • Vivek Gite July 14, 2009, 7:37 am

      Thanks for the heads-up!

  • Streametch July 10, 2009, 8:18 pm

    Any updates?

    • Vivek Gite July 14, 2009, 7:34 am

      I’ve tweaked it further. Can you test it again?

      ./svrmon.sh
      Outputs:

      -------------------------------------------------------------
      Running services status @ www031.xxxtopxxxxx.net [ Tue Jul 14 02:30:24 CDT 2009 ]
      -------------------------------------------------------------
       SSH			 : YES
       DNS			 : YES
       WEB			 : YES
       MAIL			 : YES
      -------------------------------------------------------------
      This is an automatically generated Linux service status notification by /tmp/svrmon.sh script.

      Stop named:
      # service named stop
      Run it again:

      -------------------------------------------------------------
      Running services status @ www031.xxxtopxxxxx.net [ Tue Jul 14 02:30:24 CDT 2009 ]
      -------------------------------------------------------------
       SSH			 : YES
       DNS			 : NO
       WEB			 : YES
       MAIL			 : YES
      -------------------------------------------------------------
      This is an automatically generated Linux service status notification by /tmp/svrmon.sh script.
  • Streametch June 19, 2009, 10:57 am

    -bash-3.00# chmod +x /srv/chkserv
    -bash-3.00# /srv/chkserv
    ————————————————————-
    Running services status @ server.*****.com [ Fri Jun 19 13:53:11 EEST 2009 ]
    ————————————————————-
    SSH :
    WEB : YES
    MAIL : YES
    ————————————————————-
    This is an automatically generated Linux service status notification by /srv/chkserv script.
    -bash-3.00# bash /srv/chkserv
    ————————————————————-
    Running services status @ server.*****.com [ Fri Jun 19 13:53:23 EEST 2009 ]
    ————————————————————-
    SSH :
    WEB : YES
    MAIL : YES
    ————————————————————-
    This is an automatically generated Linux service status notification by /srv/chkserv script.
    -bash-3.00# netstat -tulpn |grep ssh
    tcp 0 0 :::22 :::* LISTEN 9262/sshd
    -bash-3.00# grep port /srv/chkserv
    ports=”22 80 25″

    Any idea?

    • Streametch June 19, 2009, 11:29 am

      So now, I replace Ports in script to:
      ports=”80 25 22″
      And Services to:
      service=”WEB MAIL SSH”
      And re-run script:
      -bash-3.00# /srv/chkserv
      ————————————————————-
      Running services status @ server.*****.com [ Fri Jun 19 14:27:53 EEST 2009 ]
      ————————————————————-
      WEB : YES
      MAIL : YES
      SSH : NO
      ————————————————————-
      This is an automatically generated Linux service status notification by /srv/chkserv script.

      I don’t know why :(

      • Vivek Gite June 19, 2009, 12:38 pm

        Ok, I will look at the script this week end and see if there is any bug that is shooting an email even if service is running.

  • Streametch June 18, 2009, 4:08 pm

    Hey,
    Thanks, now it work, but I have issue with only ssh. I run sshd service on non-standart port, and replace 22 port with my settings. After thant when I run this script I got blank value.
    ————————————————————-
    Running services status @ server.****.com [ Thu Jun 18 19:07:24 EEST 2009 ]
    ————————————————————-
    SSH :
    WEB : YES
    MAIL : YES
    ————————————————————-
    This is an automatically generated Linux service status notification by checkstatus script.
    And got fake alert :( Can you help me?

    • Vivek Gite June 18, 2009, 4:30 pm

      Replace port 22 with your actual port such as #3922 in $ports i.e. from

      ports="22 80 25"

      To:

      ports="3922 80 25"
      • Streametch June 18, 2009, 4:38 pm

        Yeah, I do that at once, but still get nothing about ssh

        • Streametch June 19, 2009, 9:11 am

          -bash-3.00# sh /srv/chkserv
          ————————————————————-
          Running services status @ server.*****.com [ Fri Jun 19 12:08:57 EEST 2009 ]
          ————————————————————-
          SSH :
          WEB : YES
          MAIL : YES
          ————————————————————-
          This is an automatically generated Linux service status notification by /srv/chkserv script.
          -bash-3.00# grep Port /etc/ssh/sshd_config
          Port 22
          #GatewayPorts no
          -bash-3.00# ps aux|grep ssh
          root 16151 0.0 0.0 7004 2284 ? Ss 12:07 0:00 sshd: root@ttyp0
          root 23653 0.0 0.0 4624 632 ttyp0 S+ 12:09 0:00 grep ssh
          root 28047 0.0 0.0 4140 1044 ? Ss Jun18 0:00 /usr/sbin/sshd

          • Vivek Gite June 19, 2009, 9:41 am

            Correct way to run script is either:
            chmod +x /srv/chkserv
            /srv/chkserv

            OR
            bash /srv/chkserv
            To find current sshd port enter:
            netstat -tulpn

  • Streametch June 15, 2009, 8:47 am

    Hey, this script not workin under CentOS 4.7, script messaged all service is down:
    -bash-3.00# sh test_script.sh
    Running services status:
    SSH: No
    WEB: No
    MAIL: No
    -bash-3.00#
    But all services works fine, can you help me?

    • Vivek Gite June 15, 2009, 2:19 pm

      Try updated script. Let me know if you need any other help.

      • Samarasa June 15, 2010, 9:57 am

        Where is updated scripts

Security: Are you a robot or human?

Leave a Comment