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

by on April 10, 2008 · 33 comments

  1. #!/bin/bash
  2. # Shell script to monitor running services such as web/http, ssh, mail etc.
  3. # If service fails it will send an Email to ADMIN user
  4. # -------------------------------------------------------------------------
  5. # Copyright (c) 2006 nixCraft project <http://www.cyberciti.biz/fb/>
  6. # This script is licensed under GNU GPL version 2.0 or above
  7. # -------------------------------------------------------------------------
  8. # This script is part of nixCraft shell script collection (NSSC)
  9. # Visit http://bash.cyberciti.biz/ for more information.
  10. # ----------------------------------------------------------------------
  11. # See URL for more info
  12. # http://www.cyberciti.biz/tips/processing-the-delimited-files-using-cut-and-awk.html
  13. # ---------------------------------------------------
  14. # Last updated: Jun - 15 - 2009.
  15. ports="22 53 80 25"
  16.  
  17. # service names as per above ports
  18. service="SSH DNS WEB MAIL"
  19.  
  20. #Email id to send alert
  21. ADMINEMAIL="admin@myispname.com"
  22.  
  23. #Bin paths, set them according to your Linux distro
  24. NETSTAT=/bin/netstat
  25. MAIL=/usr/bin/mail
  26. LOGGER=/usr/bin/logger
  27. ID=/usr/bin/id
  28.  
  29. # Red hat usr uncomment
  30. MAIL=/bin/mail
  31. LOGGER=/bin/logger
  32.  
  33.  
  34. #Counters, set defaults
  35. c=1
  36. status=""
  37. sendmail=0
  38.  
  39. # set the following to 1, if you want message in /var/log/messages via a SYSLOG
  40. logtosyslog=0
  41.  
  42. # Log file used to send an email
  43. LOG="/tmp/services.log.$$"
  44.  
  45. # log message to screen and a log file
  46. log(){
  47. echo "$@"
  48. echo "$@" >> $LOG
  49. }
  50.  
  51. # log message and stop script
  52. die(){
  53. echo "$@"
  54. exit 999
  55. }
  56.  
  57. # Make sure only root can run it
  58. is_root(){
  59. local id=$($ID -u)
  60. [ $id -ne 0 ] && die "You must be root to run $0."
  61. }
  62. # Look out for all bins and create a log file
  63. init_script(){
  64. [ ! -x $MAIL ] && die "$MAIL command not found."
  65. [ ! -x $NETSTAT ] && die "$NETSTAT command not found."
  66. [ ! -x $LOGGER ] && die "$LOGGER command not found."
  67. [ ! -x $ID ] && die "$ID command not found."
  68. is_root
  69. >$LOG
  70. }
  71.  
  72.  
  73. # check for all running services and shoot an email if service is not running
  74. chk_services(){
  75. log "-------------------------------------------------------------"
  76. log "Running services status @ $(hostname) [ $(date) ]"
  77. log "-------------------------------------------------------------"
  78.  
  79. # get open ports
  80. RPORTS=$($NETSTAT -tulpn -A inet | grep -vE '^Active|Proto' | grep 'LISTEN' | awk '{ print $4}' | cut -d: -f2 | sed '/^$/d' | sort -u)
  81.  
  82. # okay let us compare them
  83. for t in $ports
  84. do
  85. sname=$(echo $service | cut -d' ' -f$c)
  86. echo -en " $sname\t\t\t : "
  87. echo -en " $sname\t\t\t : " >> $LOG
  88. for r in $RPORTS
  89. do
  90. if [ "$r" == "$t" ]
  91. then
  92. status="YES"
  93. sendmail=1
  94. break
  95. fi
  96. done
  97. echo -n "$status"
  98. echo ""
  99. echo -n "$status" >>$LOG
  100. echo "" >>$LOG
  101. # Log to a syslog /var/log/messages?
  102. # This is useful if you have a dedicated syslog server
  103. [ $logtosyslog -eq 1 ] && $LOGGER "$sname service running : $status"
  104.  
  105. # Update counters for next round
  106. c=$( expr $c + 1 )
  107. status="NO"
  108. done
  109. log "-------------------------------------------------------------"
  110. log "This is an automatically generated $(uname) service status notification by $0 script."
  111.  
  112. if [ $sendmail -eq 1 ];
  113. then
  114. $MAIL -s "Service Down @ $(hostname)" $ADMINEMAIL < $LOG
  115. fi
  116. }
  117.  
  118. ### main ###
  119. init_script
  120. chk_services
  121.  
  122. ### remove a log file ###
  123. [ -f $LOG ] && /bin/rm -f $LOG


4000+ howtos and counting! If you enjoyed this article, join 45000+ others and get free email updates!

Click here to subscribe via email.

  • hadi

    hi.. can you send to me the external script to my email hadi.utomo@gmail.com

  • shaiju

    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

  • Jesse

    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.

  • Samarasa

    Where is updated scripts

  • smeven

    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.

  • Shaiju

    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

  • Brian

    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

    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

  • MuaDDip

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

  • Aneesh

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

  • Michael Pivonka

    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
    
  • Amar

    Hi,

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

    Regards,
    Amar Sharma

  • Amar

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

Previous Script:

Next Script: