#!/bin/bash # # Source: http://www.cyberciti.biz/files/scripts/domain-check-2.txt # Program: Domain Expiration Check # # Author: Matty < matty91 at gmail dot com > # # Current Version: 1.95 # # Revision History: # Version 1.96 # Rename variables so system variables aren't potentially changed. -- Eric Renfro # Code optimization and per-whois delay capability is possible. -- Eric Renfro # Output table is now fully string size padded for results. -- Eric Renfro # 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 # Version 1.9 # Bug fix and enhancement for .uk and .co.uk -- Vivek Gite # # Version 1.8 # Bug fix added $mailContact -- Vivek Gite # # Version 1.7 # Added support for .jp domain names -- Vivek Gite # # Version 1.6 # Added support for .uk domain names; fixed a bug detecting tldtype -- Vivek Gite # # Version 1.5 # Added support for .org, .in, .biz and .info domain names -- Vivek Gite # # 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") whoisVal=$(${whois} -h "${whoisServer}" "${1}") registrar=$(echo "$whoisVal" | grep "Sponsoring Registrar:" | cut -d':' -f2) 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