scripts/domain-check
author Tomas Zeman <tzeman@volny.cz>
Mon, 05 Aug 2013 16:35:00 +0200
changeset 27 e8cb759c60b4
parent 25 4cbcc8af8481
permissions -rwxr-xr-x
merged conf/fs.conf: file.cat

#!/bin/bash 
#
# Source: http://www.cyberciti.biz/files/scripts/domain-check-2.txt
# Program: Domain Expiration Check <domain-check>
#
# Author: Matty < matty91 at gmail dot com >
# 
# Current Version: 1.96
#
# Revision History:
#  Version 1.96
#    Rename variables so system variables aren't potentially changed. -- Eric Renfro <psi-jack@linux-help.org>
#    Code optimization and per-whois delay capability is possible. -- Eric Renfro <psi-jack@linux-help.org>
#    Output table is now fully string size padded for results. -- Eric Renfro <psi-jack@linux-help.org>

#  Version 1.95
#    Added support for .ie and .us domain names
#    Cleaned up some areas where awk and cut were being called
#    directly rather than from the variables they were asigned to. -- Chris Jones <chris@sysadminchris.com>
#  Version 1.9
#    Bug fix and enhancement for .uk and .co.uk -- Vivek Gite <vivek@nixcraft.com>
#
#  Version 1.8
#    Bug fix added $MAIL -- Vivek Gite <vivek@nixcraft.com>
#
#  Version 1.7
#    Added support for .jp domain names  -- Vivek Gite <vivek@nixcraft.com>
#
#  Version 1.6
#    Added support for .uk domain names; fixed a bug detecting tldtype  -- Vivek Gite <vivek@nixcraft.com>
#
#  Version 1.5
#    Added support for .org, .in, .biz and .info domain names -- Vivek Gite <vivek@nixcraft.com>
# 
#  Version 1.4
#    Updated the documentation.
#
#  Version 1.3
#    Gracefully Handle the case where the expiration data is unavailable
#
#  Version 1.2
#    Added "-s" option to allow arbitrary registrars
#
#  Version 1.1
#    Fixed issue with 'e' getopt string -- Pedro Alves
#
#  Version 1.0
#    Initial Release
#
# Last Updated: 07-Aug-2012
#
# Purpose:
#  domain-check checks to see if a domain has expired. domain-check
#  can be run in interactive and batch mode, and provides faciltities 
#  to alarm if a domain is about to expire.
#
# License:
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Notes:
#   Since each registrar provides expiration data in a unique format (if
#   they provide it at all), domain-check is currently only able to
#   processess expiration information for a subset of the available
#   registrars.
#
# Requirements:
#   Requires whois
#
# Installation:
#   Copy the shell script to a suitable location
#
# Tested platforms:
#  -- Solaris 9 using /bin/bash
#  -- Solaris 10 using /bin/bash
#  -- OS X 10.4.2 using /bin/sh
#  -- OpenBSD using /bin/sh
#  -- FreeBSD using /bin/sh
#  -- Redhat advanced server 3.0MU3 using /bin/sh
#
# Usage:
#  Refer to the usage() sub-routine, or invoke domain-check
#  with the "-h" option.
#
# Example:
#
#  The first example will print the expiration date and registrar for prefetch.net:
#
#  $ domain-check.sh -d prefetch.net
#
#  Domain                              Registrar         Status   Expires     Days Left
#  ----------------------------------- ----------------- -------- ----------- ---------
#  prefetch.net                        INTERCOSMOS MEDIA Valid    13-feb-2006   64   
#
#  The second example prints the expiration date and registrar for the domains 
#  listed in the file "domains":
#
#  $ domain-check.sh -f domains    
#
#  Domain                              Registrar         Status   Expires     Days Left
#  ----------------------------------- ----------------- -------- ----------- ---------
#  sun.com                             NETWORK SOLUTIONS Valid    20-mar-2010   1560 
#  google.com                          EMARKMONITOR INC. Valid    14-sep-2011   2103 
#  ack.com                             NETWORK SOLUTIONS Valid    09-may-2008   880  
#  prefetch.net                        INTERCOSMOS MEDIA Valid    13-feb-2006   64   
#  spotch.com                          GANDI             Valid    03-dec-2006   357  
#
#  The third example will e-mail the address admin@prefetch.net with the domains that
#  will expire in 60-days or less:
#
#  $ domain-check -a -f domains -q -x 60 -e admin@prefetch.net  
#

PATH=/bin:/usr/bin:/usr/local/bin:/usr/local/ssl/bin:/usr/sfw/bin ; export PATH

# Who to page when an expired domain is detected (cmdline: -e)
admin="sysadmin@mydomain.com"

# Hostname to report to Zabbix Servers (cmdline: -i)
hostname="-"

# Number of days in the warning threshhold  (cmdline: -x)
warnDays=30

# If quiet is set to TRUE, don't print anything on the console (cmdline: -q)
quiet=false

# Human readable output default to off for Zabbix server processing (cmdline: -r)
human=false

# Don't send emails by default (cmdline: -a)
alarm=false

# JSON Discovery mode off by default (cmdline: -j)
json=false

# Whois server to use (cmdline: -s)
whoisServer="whois.internic.org"

# Location of system binaries
awk="/usr/bin/awk"
whois="/usr/bin/whois"
date="/bin/date"
cut="/usr/bin/cut"
mailContact="/bin/mail"

# Track tld types for query limiting:
declare -A domainPoll

#############################################################################
# Purpose: Convert a date from MONTH-DAY-YEAR to Julian format
# Acknowledgements: Code was adapted from examples in the book
#                   "Shell Scripting Recipes: A Problem-Solution Approach"
#                   ( ISBN 1590594711 )
# Arguments:
#   $1 -> Month (e.g., 06)
#   $2 -> Day   (e.g., 08)
#   $3 -> Year  (e.g., 2006)
#############################################################################
date2julian() 
{
    if [[ "${1} != "" && "${2} != "" && "${3}" != "" ]]
    then
         ## Since leap years add aday at the end of February, 
         ## calculations are done from 1 March 0000 (a fictional year)
         d2j_tmpmonth=$((12 * ${3} + ${1} - 3))
        
          ## If it is not yet March, the year is changed to the previous year
          d2j_tmpyear=$(( ${d2j_tmpmonth} / 12))
        
          ## The number of days from 1 March 0000 is calculated
          ## and the number of days from 1 Jan. 4713BC is added 
          echo $(( (734 * ${d2j_tmpmonth} + 15) / 24 -  2 * ${d2j_tmpyear} + ${d2j_tmpyear}/4
                        - ${d2j_tmpyear}/100 + ${d2j_tmpyear}/400 + $2 + 1721119 ))
    else
          echo 0
    fi
}

#############################################################################
# Purpose: Convert a string month into an integer representation
# Arguments:
#   $1 -> Month name (e.g., Sep)
#############################################################################
getmonth() 
{
       case ${1,,} in
             jan) echo 1 ;;
             feb) echo 2 ;;
             mar) echo 3 ;;
             apr) echo 4 ;;
             may) echo 5 ;;
             jun) echo 6 ;;
             jul) echo 7 ;;
             aug) echo 8 ;;
             sep) echo 9 ;;
             oct) echo 10 ;;
             nov) echo 11 ;;
             dec) echo 12 ;;
               *) echo 0 ;;
       esac
}

#############################################################################
# Purpose: Calculate the number of seconds between two dates
# Arguments:
#   $1 -> Date #1
#   $2 -> Date #2
#############################################################################
date_diff() 
{
        if [[ "${1}" != "" && "${2}" != "" ]]
        then
                echo $(expr ${2} - ${1})
        else
                echo 0
        fi
}

##################################################################
# Purpose: Access whois data to grab the registrar and expiration date
# Arguments:
#   $1 -> Domain to check
##################################################################
check_domain_status() 
{
    local registrar=""
    # Avoid whois LIMIT EXCEEDED - slowdown our whois client by adding 3 sec 
    #sleep 3
    # Save the domain since set will trip up the ordering
    domain=${1}
    tldType="$(echo ${domain} | ${cut} -d '.' -f3 | tr '[A-Z]' '[a-z]')" 
    if [[ "${tldType}"  = "" ]];
    then
	    tldType="$(echo ${domain} | ${cut} -d '.' -f2 | tr '[A-Z]' '[a-z]')" 
    fi

    # Invoke whois to find the domain registrar and expiration date
    #whoisVal=$(${whois} -h ${whoisServer} "=${1}")
    # Let whois select server 
   
    # The whois Expiration data should resemble the following: "Expiration Date: 09-may-2008"
    case $tldType in
        "org")  [[ -n ${domainPoll[$tldType]} ]] && sleep 15
                whoisVal=$(${whois} -h "whois.pir.org" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                domainDate=$(echo "${whoisVal}" | ${awk} '/Expiration Date:/ { print $2 }' | ${cut} -d':' -f2)
                ;;
        "in")   whoisVal=$(${whois} -h "whois.registry.in" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                domainDate=$(echo "${whoisVal}" | ${awk} '/Expiration Date:/ { print $2 }' | ${cut} -d':' -f2)
                ;;
        "uk")   whoisVal=$(${whois} -h "whois.nic.uk" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                domainDate=$(echo "${whoisVal}" | ${awk} '/Renewal date:/ || /Expiry date:/ { print $3 }')
                ;;
        "biz")  whoisVal=$(${whois} -h "whois.neulevel.biz" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                domainDate=$(echo "${whoisVal}" | ${awk} '/Domain Expiration Date:/ { print $6"-"$5"-"$9 }')
                ;;
        "info") whoisVal=$(${whois} -h "whois.afilias.info" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                domainDate=$(echo "${whoisVal}" | ${awk} '/Expiration Date:/ { print $2 }' | ${cut} -d':' -f2)
                ;;
        "us")   whoisVal=$(${whois} -h "whois.nic.us" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                domainDate=$(echo "${whoisVal}" | ${awk} '/Domain Expiration Date:/ { print $6"-"$5"-"$9 }')
                ;;
        "com" | "net" | "edu")
                whoisVal=$(${whois} -h "whois.internic.org" "${1}")
                registrar=$(echo "$whoisVal" | grep "Registrar:" | sed -e 's/^[ \t]*//g' -e 's/[ \t]*$//g' | cut -d':' -f2 | sed -e 's/^[ \t]*//g')
                domainDate=$(echo "${whoisVal}" | ${awk} '/Expiration/ { print $NF }')

                #echo "Registrar = $registrar"
                #exit 0
                ;;
        "ie")   whoisVal=$(${whois} -h "whois.domainregistry.ie" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                tdomdate=$(echo "${whoisVal}" | ${awk} '/renewal/ { print $2 }')
                tyear=$(echo ${tdomdate} | ${cut} -d'-' -f3)
                tmon=$(echo ${tdomdate} | ${cut} -d'-' -f2)
    	        case ${tmon} in
    	            "January")      tmonth=jan ;;
    	            "February")     tmonth=feb ;;
    	            "March")        tmonth=mar ;;
    	            "April")        tmonth=apr ;;
    	            "May")          tmonth=may ;;
    	            "June")         tmonth=jun ;;
    	            "July")         tmonth=jul ;;
    	            "August")       tmonth=aug ;;
    	            "September")    tmonth=sep ;;
    	            "October")      tmonth=oct ;;
    	            "November")     tmonth=nov ;;
    	            "December")     tmonth=dec ;;
                   	*)              tmonth=0   ;;
    		    esac
                tday=$(echo ${tdomdate} | ${cut} -d'-' -f1)
    	        domainDate=$(echo $tday-$tmonth-$tyear)
                ;;
        "jp")   whoisVal=$(${whois} -h "whois.jprs.jp" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
        	    tdomdate=$(echo "${whoisVal}" | ${awk} '/Expires on/ { print $3 }')
                tyear=$(echo ${tdomdate} | ${cut} -d'/' -f1)
                tmon=$(echo ${tdomdate} | ${cut} -d'/' -f2)
    	        case ${tmon} in
    	             1|01)  tmonth=jan ;;
    	             2|02)  tmonth=feb ;;
    	             3|03)  tmonth=mar ;;
    	             4|04)  tmonth=apr ;;
    	             5|05)  tmonth=may ;;
    	             6|06)  tmonth=jun ;;
    	             7|07)  tmonth=jul ;;
    	             8|08)  tmonth=aug ;;
    	             9|09)  tmonth=sep ;;
    	             10)    tmonth=oct ;;
    	             11)    tmonth=nov ;;
    	             12)    tmonth=dec ;;
                   	 *)     tmonth=0   ;;
    		    esac
                tday=$(echo ${tdomdate} | ${cut} -d'/' -f3)
    	        domainDate=$(echo $tday-$tmonth-$tyear)
                ;;
        "cz")   [[ -n ${domainPoll[$tldType]} ]] && sleep 20
                whoisVal=$(${whois} -h "whois.nic.cz" "${1}")
                registrar=$(echo "$whoisVal" | grep "registrar:" | head -1 | cut -d':' -f2 | sed -e 's/^ *//' -e 's/ *$//')
                tdomdate=$(echo "${whoisVal}" | awk '/expire:/ { print $2 }')
                tyear=$(echo ${tdomdate} | cut -d'.' -f3)
                tmon=$(echo ${tdomdate} | cut -d'.' -f2)
                tday=$(echo ${tdomdate} | cut -d'.' -f1)
                case ${tmon} in
                    1|01) tmonth=jan ;;
                    2|02) tmonth=feb ;;
                    3|03) tmonth=mar ;;
                    4|04) tmonth=apr ;;
                    5|05) tmonth=may ;;
                    6|06) tmonth=jun ;;
                    7|07) tmonth=jul ;;
                    8|08) tmonth=aug ;;
                    9|09) tmonth=sep ;;
                    10)   tmonth=oct ;;
                    11)   tmonth=nov ;;
                    12)   tmonth=dec ;;
                    *)    tmonth=0   ;;
                esac
                domainDate=$(echo $tday-$tmonth-$tyear)
                ;;
        *)      whoisVal=$(${whois} -h "${whoisServer}" "${1}")
                registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2)
                domainDate=$(echo "${whoisVal}" | ${awk} '/Expiration/ { print $NF }')
                ;;
    esac

    if [[ -z ${domainPoll[$tldType]} ]]; then
        domainPoll[$tldType]=1
    else
        let domainPoll[$tldType]++
    fi

    # If the Registrar is NULL, then we didn't get any data
    #if [[ "${registrar}" = "" ]]
    #then
    #    prints "$domain" "Unknown" "Unknown" "Unknown" "Unknown"
    #    return
    #fi

    #echo $domainDate # debug 
    # Whois data should be in the following format: "13-feb-2006"
    IFS="-"
    set -- ${domainDate}
    month=$(getmonth ${2})
    IFS=""

    # Convert the date to seconds, and get the diff between NOW and the expiration date
    domainJulian=$(date2julian ${month} ${1#0} ${3})
    domainDiff=$(date_diff ${nowJulian} ${domainJulian})

    if ! $human
    then
        echo "$hostname domain.daysleft[${domain}] ${domainDiff}"
    fi

    if [[ ${domainDiff} -lt 0 ]]
    then
        if $alarm
        then
            echo "The domain ${domain} has expired!" \
                | ${mailContact} -s "Domain ${domain} has expired!" ${admin}
        fi
        prints ${domain} "Expired" "${domainDate}" "${domainDiff}" ${registrar}
    elif [[ ${domainDiff} -lt ${warnDays} ]]
    then
        if $alarm
        then
            echo "The domain ${domain} will expire on ${domainDate}" \
                | ${mailContact} -s "Domain ${domain} will expire in ${warnDays}-days or less" ${admin}
        fi
        prints ${domain} "Expiring" "${domainDate}"  "${registrar}"
    else
        prints ${domain} "Valid" "${domainDate}"  "${domainDiff}" "${registrar}"
    fi
}

####################################################
# Purpose: Print a heading with the relevant columns
# Arguments:
#   None
####################################################
print_heading()
{
    if $human
    then
        if ! $quiet
        then
            printf "\n%-35s %-17s %-8s %-11s %-5s\n" "Domain" "Registrar" "Status" "Expires" "Days Left"
            echo "----------------------------------- ----------------- -------- ----------- ---------"
        fi
    fi
}

#####################################################################
# Purpose: Print a line with the expiraton interval
# Arguments:
#   $1 -> Domain
#   $2 -> Status of domain (e.g., expired or valid)
#   $3 -> Date when domain will expire
#   $4 -> Days left until the domain will expire
#   $5 -> Domain registrar
#####################################################################
prints()
{
    if $human
    then
        if ! $quiet
        then
            minDate=$(echo $3 | ${awk} '{ print $1, $2, $4 }')
            printf "%-35s %-17s %-8s %-11s %-5s\n" "${1:0:35}" "${5:0:17}" "${2:0:8}" "${minDate:0:11}" "${4:0:5}"
        fi
    fi
}

##########################################
# Purpose: Describe how the script works
# Arguments:
#   None
##########################################
usage()
{
        #app="$(basename $0)"
        echo "Usage:" >&2
        echo "Zabbix Agent Mode:" >&2
        echo "  [-s whois_host] [-i hostname] <-d domain | -f file>" >&2
        echo "Human Readable Mode:" >&2
        echo "  -r [-q][-a] [-e email] [-x days] [-s host] <-d domain|-f file>" >&2
        echo "JSON Mode:" >&2
        echo "  -j -f domainfile" >&2
        echo ""  >&2
        echo "  -a               : Send a warning message through email " >&2
        echo "  -d domain        : Domain to analyze (interactive mode)" >&2
        echo "  -e email address : Email address to send expiration notices" >&2
        echo "  -f domain file   : File with a list of domains" >&2
        echo "  -h               : Print this screen" >&2
        echo "  -i hostname      : Hostname for Zabbix Server" >&2
        echo "  -j               : Discovery JSON Object for Zabbix auto-discovery, (needs -f)" >&2
        echo "  -r               : Human Readable" >&2
        echo "  -s whois server  : Whois sever to query for information" >&2
        echo "  -q               : Don't print anything on the console" >&2
        echo "  -x days          : Domain expiration interval (eg. if domain_ date < days)" >&2
        echo "" >&2
}

### Evaluate the options passed on the command line
while getopts ae:f:i:jrhd:s:qx: option
do
        case "${option}"
        in
                a) alarm=true;;
                e) admin=${OPTARG};;
                d) domain=${OPTARG};;
                f) serverFile=$OPTARG;;
                i) hostname=$OPTARG;;
                j) json=true;;
                r) human=true;;
                s) whoisServer=$OPTARG;;
                q) quiet=true;;
                x) warnDays=$OPTARG;;
                \?) usage
                    exit 1;;
        esac
done

### Check to see if the whois binary exists
if [[ ! -f ${whois} ]]
then
        echo "ERROR: The whois binary does not exist in ${whois}." >&2
        echo "  FIX: Please modify the \$whois variable in the program header." >&2
        exit 1
fi

### Check to make sure a date utility is available
if [[ ! -f ${date} ]]
then
        echo "ERROR: The date binary does not exist in ${date}." >&2
        echo "  FIX: Please modify the \$date variable in the program header." >&2
        exit 1
fi

### Baseline the dates so we have something to compare to
month=$(${date} "+%m")
DAY=$(${date} "+%d")
YEAR=$(${date} "+%Y")
nowJulian=$(date2julian ${month#0} ${DAY#0} ${YEAR})

### If a HOST and PORT were passed on the cmdline, use those values
if $json
then
    if [[ -f "${serverFile}" ]]
    then
        echo "{"
        echo "  \"data\":["
        echo
        while read domain
        do
            echo "  { \"{#DOMAIN}\":\"${domain}\" },"
        done < ${serverFile}
        echo
        echo "  ]"
        echo "}"
    else
        usage
        exit 1
    fi
else
    if [[ "${domain}" != "" ]]
    then
            print_heading
            check_domain_status "${domain}"
    ### If a file and a "-a" are passed on the command line, check all
    ### of the domains in the file to see if they are about to expire
    elif [[ -f "${serverFile}" ]]
    then
            print_heading
            while read domain
            do
                    #sleep 30
                    check_domain_status "${domain}"

            done < ${serverFile}

    ### There was an error, so print a detailed usage message and exit
    else
            usage
            exit 1
    fi

    # Add an extra newline
    if $human
    then
        echo
    fi
fi

### Exit with a success indicator
exit 0

# vim: et ts=4 sw=4