scripts/domain-check
changeset 19 08238959d9fc
child 20 fe1c8b4725f7
equal deleted inserted replaced
18:01a815c167f5 19:08238959d9fc
       
     1 #!/bin/bash 
       
     2 #
       
     3 # Source: http://www.cyberciti.biz/files/scripts/domain-check-2.txt
       
     4 # Program: Domain Expiration Check <domain-check>
       
     5 #
       
     6 # Author: Matty < matty91 at gmail dot com >
       
     7 # 
       
     8 # Current Version: 1.9
       
     9 #
       
    10 # Revision History:
       
    11 #  Version 1.9
       
    12 #    Bug fix and enhancement for .uk and .co.uk -- Vivek Gite <vivek@nixcraft.com>
       
    13 #
       
    14 #  Version 1.8
       
    15 #    Bug fix added $MAIL -- Vivek Gite <vivek@nixcraft.com>
       
    16 #
       
    17 #  Version 1.7
       
    18 #    Added support for .jp domain names  -- Vivek Gite <vivek@nixcraft.com>
       
    19 #
       
    20 #  Version 1.6
       
    21 #    Added support for .uk domain names; fixed a bug detecting tldtype  -- Vivek Gite <vivek@nixcraft.com>
       
    22 #
       
    23 #  Version 1.5
       
    24 #    Added support for .org, .in, .biz and .info domain names -- Vivek Gite <vivek@nixcraft.com>
       
    25 # 
       
    26 #  Version 1.4
       
    27 #    Updated the documentation.
       
    28 #
       
    29 #  Version 1.3
       
    30 #    Gracefully Handle the case where the expiration data is unavailable
       
    31 #
       
    32 #  Version 1.2
       
    33 #    Added "-s" option to allow arbitrary registrars
       
    34 #
       
    35 #  Version 1.1
       
    36 #    Fixed issue with 'e' getopt string -- Pedro Alves
       
    37 #
       
    38 #  Version 1.0
       
    39 #    Initial Release
       
    40 #
       
    41 # Last Updated: 07-Aug-2012
       
    42 #
       
    43 # Purpose:
       
    44 #  domain-check checks to see if a domain has expired. domain-check
       
    45 #  can be run in interactive and batch mode, and provides faciltities 
       
    46 #  to alarm if a domain is about to expire.
       
    47 #
       
    48 # License:
       
    49 #  This program is distributed in the hope that it will be useful,
       
    50 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    51 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
       
    52 #
       
    53 # Notes:
       
    54 #   Since each registrar provides expiration data in a unique format (if
       
    55 #   they provide it at all), domain-check is currently only able to
       
    56 #   processess expiration information for a subset of the available
       
    57 #   registrars.
       
    58 #
       
    59 # Requirements:
       
    60 #   Requires whois
       
    61 #
       
    62 # Installation:
       
    63 #   Copy the shell script to a suitable location
       
    64 #
       
    65 # Tested platforms:
       
    66 #  -- Solaris 9 using /bin/bash
       
    67 #  -- Solaris 10 using /bin/bash
       
    68 #  -- OS X 10.4.2 using /bin/sh
       
    69 #  -- OpenBSD using /bin/sh
       
    70 #  -- FreeBSD using /bin/sh
       
    71 #  -- Redhat advanced server 3.0MU3 using /bin/sh
       
    72 #
       
    73 # Usage:
       
    74 #  Refer to the usage() sub-routine, or invoke domain-check
       
    75 #  with the "-h" option.
       
    76 #
       
    77 # Example:
       
    78 #
       
    79 #  The first example will print the expiration date and registrar for prefetch.net:
       
    80 #
       
    81 #  $ domain-check.sh -d prefetch.net
       
    82 #
       
    83 #  Domain                              Registrar         Status   Expires     Days Left
       
    84 #  ----------------------------------- ----------------- -------- ----------- ---------
       
    85 #  prefetch.net                        INTERCOSMOS MEDIA Valid    13-feb-2006   64   
       
    86 #
       
    87 #  The second example prints the expiration date and registrar for the domains 
       
    88 #  listed in the file "domains":
       
    89 #
       
    90 #  $ domain-check.sh -f domains    
       
    91 #
       
    92 #  Domain                              Registrar         Status   Expires     Days Left
       
    93 #  ----------------------------------- ----------------- -------- ----------- ---------
       
    94 #  sun.com                             NETWORK SOLUTIONS Valid    20-mar-2010   1560 
       
    95 #  google.com                          EMARKMONITOR INC. Valid    14-sep-2011   2103 
       
    96 #  ack.com                             NETWORK SOLUTIONS Valid    09-may-2008   880  
       
    97 #  prefetch.net                        INTERCOSMOS MEDIA Valid    13-feb-2006   64   
       
    98 #  spotch.com                          GANDI             Valid    03-dec-2006   357  
       
    99 #
       
   100 #  The third example will e-mail the address admin@prefetch.net with the domains that
       
   101 #  will expire in 60-days or less:
       
   102 #
       
   103 #  $ domain-check -a -f domains -q -x 60 -e admin@prefetch.net  
       
   104 #
       
   105 
       
   106 PATH=/bin:/usr/bin:/usr/local/bin:/usr/local/ssl/bin:/usr/sfw/bin ; export PATH
       
   107 
       
   108 # Who to page when an expired domain is detected (cmdline: -e)
       
   109 ADMIN="sysadmin@mydomain.com"
       
   110 
       
   111 # Number of days in the warning threshhold  (cmdline: -x)
       
   112 WARNDAYS=30
       
   113 
       
   114 # If QUIET is set to TRUE, don't print anything on the console (cmdline: -q)
       
   115 QUIET="FALSE"
       
   116 
       
   117 # Don't send emails by default (cmdline: -a)
       
   118 ALARM="FALSE"
       
   119 
       
   120 # Whois server to use (cmdline: -s)
       
   121 WHOIS_SERVER="whois.internic.org"
       
   122 
       
   123 # Location of system binaries
       
   124 AWK="/usr/bin/awk"
       
   125 WHOIS="/usr/bin/whois"
       
   126 DATE="/bin/date"
       
   127 CUT="/usr/bin/cut"
       
   128 MAIL="/bin/mail"
       
   129 # Place to stash temporary files
       
   130 WHOIS_TMP="/var/tmp/whois.$$"
       
   131 
       
   132 #############################################################################
       
   133 # Purpose: Convert a date from MONTH-DAY-YEAR to Julian format
       
   134 # Acknowledgements: Code was adapted from examples in the book
       
   135 #                   "Shell Scripting Recipes: A Problem-Solution Approach"
       
   136 #                   ( ISBN 1590594711 )
       
   137 # Arguments:
       
   138 #   $1 -> Month (e.g., 06)
       
   139 #   $2 -> Day   (e.g., 08)
       
   140 #   $3 -> Year  (e.g., 2006)
       
   141 #############################################################################
       
   142 date2julian() 
       
   143 {
       
   144     if [ "${1} != "" ] && [ "${2} != ""  ] && [ "${3}" != "" ]
       
   145     then
       
   146          ## Since leap years add aday at the end of February, 
       
   147          ## calculations are done from 1 March 0000 (a fictional year)
       
   148          d2j_tmpmonth=$((12 * ${3} + ${1} - 3))
       
   149         
       
   150           ## If it is not yet March, the year is changed to the previous year
       
   151           d2j_tmpyear=$(( ${d2j_tmpmonth} / 12))
       
   152         
       
   153           ## The number of days from 1 March 0000 is calculated
       
   154           ## and the number of days from 1 Jan. 4713BC is added 
       
   155           echo $(( (734 * ${d2j_tmpmonth} + 15) / 24 -  2 * ${d2j_tmpyear} + ${d2j_tmpyear}/4
       
   156                         - ${d2j_tmpyear}/100 + ${d2j_tmpyear}/400 + $2 + 1721119 ))
       
   157     else
       
   158           echo 0
       
   159     fi
       
   160 }
       
   161 
       
   162 #############################################################################
       
   163 # Purpose: Convert a string month into an integer representation
       
   164 # Arguments:
       
   165 #   $1 -> Month name (e.g., Sep)
       
   166 #############################################################################
       
   167 getmonth() 
       
   168 {
       
   169        LOWER=`tolower $1`
       
   170               
       
   171        case ${LOWER} in
       
   172              jan) echo 1 ;;
       
   173              feb) echo 2 ;;
       
   174              mar) echo 3 ;;
       
   175              apr) echo 4 ;;
       
   176              may) echo 5 ;;
       
   177              jun) echo 6 ;;
       
   178              jul) echo 7 ;;
       
   179              aug) echo 8 ;;
       
   180              sep) echo 9 ;;
       
   181              oct) echo 10 ;;
       
   182              nov) echo 11 ;;
       
   183              dec) echo 12 ;;
       
   184                *) echo  0 ;;
       
   185        esac
       
   186 }
       
   187 
       
   188 #############################################################################
       
   189 # Purpose: Calculate the number of seconds between two dates
       
   190 # Arguments:
       
   191 #   $1 -> Date #1
       
   192 #   $2 -> Date #2
       
   193 #############################################################################
       
   194 date_diff() 
       
   195 {
       
   196         if [ "${1}" != "" ] &&  [ "${2}" != "" ]
       
   197         then
       
   198                 echo $(expr ${2} - ${1})
       
   199         else
       
   200                 echo 0
       
   201         fi
       
   202 }
       
   203 
       
   204 ##################################################################
       
   205 # Purpose: Converts a string to lower case
       
   206 # Arguments:
       
   207 #   $1 -> String to convert to lower case
       
   208 ##################################################################
       
   209 tolower() 
       
   210 {
       
   211      LOWER=`echo ${1} | tr [A-Z] [a-z]`
       
   212      echo $LOWER
       
   213 }
       
   214 
       
   215 ##################################################################
       
   216 # Purpose: Access whois data to grab the registrar and expiration date
       
   217 # Arguments:
       
   218 #   $1 -> Domain to check
       
   219 ##################################################################
       
   220 check_domain_status() 
       
   221 {
       
   222     local REGISTRAR=""
       
   223     # Avoid WHOIS LIMIT EXCEEDED - slowdown our whois client by adding 3 sec 
       
   224     sleep 3
       
   225     # Save the domain since set will trip up the ordering
       
   226     DOMAIN=${1}
       
   227     TLDTYPE="`echo ${DOMAIN} | cut -d '.' -f3 | tr '[A-Z]' '[a-z]'`" 
       
   228     if [ "${TLDTYPE}"  == "" ];
       
   229     then
       
   230 	    TLDTYPE="`echo ${DOMAIN} | cut -d '.' -f2 | tr '[A-Z]' '[a-z]'`" 
       
   231     fi
       
   232 
       
   233     # Invoke whois to find the domain registrar and expiration date
       
   234     #${WHOIS} -h ${WHOIS_SERVER} "=${1}" > ${WHOIS_TMP}
       
   235     # Let whois select server 
       
   236     if [ "${TLDTYPE}"  == "org" ];
       
   237     then
       
   238         ${WHOIS} -h "whois.pir.org" "${1}" > ${WHOIS_TMP}
       
   239     elif [ "${TLDTYPE}"  == "in" ]; # India
       
   240     then
       
   241         ${WHOIS} -h "whois.registry.in" "${1}" > ${WHOIS_TMP}
       
   242     elif [ "${TLDTYPE}"  == "uk" ]; # United Kingdom  
       
   243     then
       
   244         ${WHOIS} -h "whois.nic.uk" "${1}" > ${WHOIS_TMP}
       
   245 
       
   246     elif [ "${TLDTYPE}"  == "biz" ];
       
   247     then
       
   248         ${WHOIS} -h "whois.neulevel.biz" "${1}" > ${WHOIS_TMP}
       
   249     elif [ "${TLDTYPE}"  == "info" ];
       
   250     then
       
   251         ${WHOIS} -h "whois.afilias.info" "${1}" > ${WHOIS_TMP}
       
   252     elif [ "${TLDTYPE}"  == "jp" ]; # Japan
       
   253     then
       
   254         ${WHOIS} -h "whois.jprs.jp" "${1}" > ${WHOIS_TMP}
       
   255 
       
   256     elif [ "${TLDTYPE}"  == "com" -o "${TLDTYPE}"  == "net" -o "${TLDTYPE}"  == "edu" ];
       
   257     then
       
   258 	${WHOIS} -h ${WHOIS_SERVER} "=${1}" > ${WHOIS_TMP}
       
   259     else
       
   260 	${WHOIS} "${1}" > ${WHOIS_TMP}
       
   261     fi
       
   262 
       
   263     # Parse out the expiration date and registrar -- uses the last registrar it finds
       
   264     REGISTRAR=`cat ${WHOIS_TMP} | ${AWK} -F: '/Registrar/ && $2 != ""  { REGISTRAR=substr($2,2,17) } END { print REGISTRAR }'`
       
   265 
       
   266     if [ "${TLDTYPE}" == "uk" ]; # for .uk domain
       
   267     then
       
   268 	REGISTRAR=`cat ${WHOIS_TMP} | ${AWK} -F: '/Registrar:/ && $0 != ""  { getline; REGISTRAR=substr($0,2,17) } END { print REGISTRAR }'`
       
   269     elif [ "${TLDTYPE}" == "jp" ];
       
   270     then
       
   271         REGISTRAR=`cat ${WHOIS_TMP} | ${AWK} '/Registrant/ && $2 != ""  { REGISTRAR=substr($2,1,17) } END { print REGISTRAR }'`
       
   272     fi
       
   273 
       
   274     # If the Registrar is NULL, then we didn't get any data
       
   275     if [ "${REGISTRAR}" = "" ]
       
   276     then
       
   277         prints "$DOMAIN" "Unknown" "Unknown" "Unknown" "Unknown"
       
   278         return
       
   279     fi
       
   280 
       
   281     # The whois Expiration data should resemble the following: "Expiration Date: 09-may-2008"
       
   282 
       
   283     # for .in, .info, .org domains
       
   284     if [ "${TLDTYPE}" == "in" -o "${TLDTYPE}" == "info" -o "${TLDTYPE}" == "org" ];
       
   285     then
       
   286 	    DOMAINDATE=`cat ${WHOIS_TMP} | ${AWK} '/Expiration Date:/ { print $2 }' | cut -d':' -f2`
       
   287     elif [ "${TLDTYPE}" == "biz" ]; # for .biz domain
       
   288     then
       
   289             DOMAINDATE=`cat ${WHOIS_TMP} | awk '/Domain Expiration Date:/ { print $6"-"$5"-"$9 }'`
       
   290     elif [ "${TLDTYPE}" == "uk" ]; # for .uk domain
       
   291     then
       
   292             DOMAINDATE=`cat ${WHOIS_TMP} | awk '/Renewal date:/ || /Expiry date:/ { print $3 }'`
       
   293     elif [ "${TLDTYPE}" == "jp" ]; # for .jp 2010/04/30
       
   294     then
       
   295 	    tdomdate=`cat ${WHOIS_TMP} | awk '/Expires on/ { print $3 }'`
       
   296             tyear=`echo ${tdomdate} | cut -d'/' -f1`
       
   297             tmon=`echo ${tdomdate} | cut -d'/' -f2`
       
   298 	       case ${tmon} in
       
   299 	             1|01) tmonth=jan ;;
       
   300 	             2|02) tmonth=feb ;;
       
   301 	             3|03) tmonth=mar ;;
       
   302 	             4|04) tmonth=apr ;;
       
   303 	             5|05) tmonth=may ;;
       
   304 	             6|06) tmonth=jun ;;
       
   305 	             7|07) tmonth=jul ;;
       
   306 	             8|08) tmonth=aug ;;
       
   307 	             9|09) tmonth=sep ;;
       
   308 	             10)tmonth=oct ;;
       
   309 	             11) tmonth=nov ;;
       
   310 	             12) tmonth=dec ;;
       
   311                	      *) tmonth=0 ;;
       
   312 		esac
       
   313             tday=`echo ${tdomdate} | cut -d'/' -f3`
       
   314 	    DOMAINDATE=`echo $tday-$tmonth-$tyear`
       
   315     else # .com, .edu, .net and may work with others	 
       
   316 	    DOMAINDATE=`cat ${WHOIS_TMP} | ${AWK} '/Expiration/ { print $NF }'`	
       
   317     fi
       
   318 
       
   319     #echo $DOMAINDATE # debug 
       
   320     # Whois data should be in the following format: "13-feb-2006"
       
   321     IFS="-"
       
   322     set -- ${DOMAINDATE}
       
   323     MONTH=$(getmonth ${2})
       
   324     IFS=""
       
   325 
       
   326     # Convert the date to seconds, and get the diff between NOW and the expiration date
       
   327     DOMAINJULIAN=$(date2julian ${MONTH} ${1#0} ${3})
       
   328     DOMAINDIFF=$(date_diff ${NOWJULIAN} ${DOMAINJULIAN})
       
   329 
       
   330     if [ ${DOMAINDIFF} -lt 0 ]
       
   331     then
       
   332           if [ "${ALARM}" = "TRUE" ]
       
   333           then
       
   334                 echo "The domain ${DOMAIN} has expired!" \
       
   335                 | ${MAIL} -s "Domain ${DOMAIN} has expired!" ${ADMIN}
       
   336            fi
       
   337 
       
   338            prints ${DOMAIN} "Expired" "${DOMAINDATE}" "${DOMAINDIFF}" ${REGISTRAR}
       
   339 
       
   340     elif [ ${DOMAINDIFF} -lt ${WARNDAYS} ]
       
   341     then
       
   342            if [ "${ALARM}" = "TRUE" ]
       
   343            then
       
   344                     echo "The domain ${DOMAIN} will expire on ${DOMAINDATE}" \
       
   345                     | ${MAIL} -s "Domain ${DOMAIN} will expire in ${WARNDAYS}-days or less" ${ADMIN}
       
   346             fi
       
   347             prints ${DOMAIN} "Expiring" "${DOMAINDATE}" "${DOMAINDIFF}" "${REGISTRAR}"
       
   348      else
       
   349             prints ${DOMAIN} "Valid" "${DOMAINDATE}"  "${DOMAINDIFF}" "${REGISTRAR}"
       
   350      fi
       
   351 }
       
   352 
       
   353 ####################################################
       
   354 # Purpose: Print a heading with the relevant columns
       
   355 # Arguments:
       
   356 #   None
       
   357 ####################################################
       
   358 print_heading()
       
   359 {
       
   360         if [ "${QUIET}" != "TRUE" ]
       
   361         then
       
   362                 printf "\n%-35s %-17s %-8s %-11s %-5s\n" "Domain" "Registrar" "Status" "Expires" "Days Left"
       
   363                 echo "----------------------------------- ----------------- -------- ----------- ---------"
       
   364         fi
       
   365 }
       
   366 
       
   367 #####################################################################
       
   368 # Purpose: Print a line with the expiraton interval
       
   369 # Arguments:
       
   370 #   $1 -> Domain
       
   371 #   $2 -> Status of domain (e.g., expired or valid)
       
   372 #   $3 -> Date when domain will expire
       
   373 #   $4 -> Days left until the domain will expire
       
   374 #   $5 -> Domain registrar
       
   375 #####################################################################
       
   376 prints()
       
   377 {
       
   378     if [ "${QUIET}" != "TRUE" ]
       
   379     then
       
   380             MIN_DATE=$(echo $3 | ${AWK} '{ print $1, $2, $4 }')
       
   381             printf "%-35s %-17s %-8s %-11s %-5s\n" "$1" "$5" "$2" "$MIN_DATE" "$4"
       
   382     fi
       
   383 }
       
   384 
       
   385 ##########################################
       
   386 # Purpose: Describe how the script works
       
   387 # Arguments:
       
   388 #   None
       
   389 ##########################################
       
   390 usage()
       
   391 {
       
   392         echo "Usage: $0 [ -e email ] [ -x expir_days ] [ -q ] [ -a ] [ -h ]"
       
   393         echo "          {[ -d domain_namee ]} || { -f domainfile}"
       
   394         echo ""
       
   395         echo "  -a               : Send a warning message through email "
       
   396         echo "  -d domain        : Domain to analyze (interactive mode)"
       
   397         echo "  -e email address : Email address to send expiration notices"
       
   398         echo "  -f domain file   : File with a list of domains"
       
   399         echo "  -h               : Print this screen"
       
   400         echo "  -s whois server  : Whois sever to query for information"
       
   401         echo "  -q               : Don't print anything on the console"
       
   402         echo "  -x days          : Domain expiration interval (eg. if domain_date < days)"
       
   403         echo ""
       
   404 }
       
   405 
       
   406 ### Evaluate the options passed on the command line
       
   407 while getopts ae:f:hd:s:qx: option
       
   408 do
       
   409         case "${option}"
       
   410         in
       
   411                 a) ALARM="TRUE";;
       
   412                 e) ADMIN=${OPTARG};;
       
   413                 d) DOMAIN=${OPTARG};;
       
   414                 f) SERVERFILE=$OPTARG;;
       
   415                 s) WHOIS_SERVER=$OPTARG;;
       
   416                 q) QUIET="TRUE";;
       
   417                 x) WARNDAYS=$OPTARG;;
       
   418                 \?) usage
       
   419                     exit 1;;
       
   420         esac
       
   421 done
       
   422 
       
   423 ### Check to see if the whois binary exists
       
   424 if [ ! -f ${WHOIS} ]
       
   425 then
       
   426         echo "ERROR: The whois binary does not exist in ${WHOIS} ."
       
   427         echo "  FIX: Please modify the \$WHOIS variable in the program header."
       
   428         exit 1
       
   429 fi
       
   430 
       
   431 ### Check to make sure a date utility is available
       
   432 if [ ! -f ${DATE} ]
       
   433 then
       
   434         echo "ERROR: The date binary does not exist in ${DATE} ."
       
   435         echo "  FIX: Please modify the \$DATE variable in the program header."
       
   436         exit 1
       
   437 fi
       
   438 
       
   439 ### Baseline the dates so we have something to compare to
       
   440 MONTH=$(${DATE} "+%m")
       
   441 DAY=$(${DATE} "+%d")
       
   442 YEAR=$(${DATE} "+%Y")
       
   443 NOWJULIAN=$(date2julian ${MONTH#0} ${DAY#0} ${YEAR})
       
   444 
       
   445 ### Touch the files prior to using them
       
   446 touch ${WHOIS_TMP}
       
   447 
       
   448 ### If a HOST and PORT were passed on the cmdline, use those values
       
   449 if [ "${DOMAIN}" != "" ]
       
   450 then
       
   451         print_heading
       
   452         check_domain_status "${DOMAIN}"
       
   453 ### If a file and a "-a" are passed on the command line, check all
       
   454 ### of the domains in the file to see if they are about to expire
       
   455 elif [ -f "${SERVERFILE}" ]
       
   456 then
       
   457         print_heading
       
   458         while read DOMAIN
       
   459         do
       
   460                 check_domain_status "${DOMAIN}"
       
   461 
       
   462         done < ${SERVERFILE}
       
   463 
       
   464 ### There was an error, so print a detailed usage message and exit
       
   465 else
       
   466         usage
       
   467         exit 1
       
   468 fi
       
   469 
       
   470 # Add an extra newline
       
   471 echo
       
   472 
       
   473 ### Remove the temporary files
       
   474 rm -f ${WHOIS_TMP}
       
   475 
       
   476 ### Exit with a success indicator
       
   477 exit 0
       
   478