Originally published October 29, 2018 @ 1:05 pm

This was a silly solution to a silly problem, but may come in handy in the future for other things. A user process was establishing frequent connections to a handful of FQDNs. Not having any IP caching capability, every connection attempt was preceded by DNS lookup.

When DNS was slow, the process experienced major meltdown. An easy “fix” was to add those FQDNs to /etc/hosts. Even though they were fairly static, I did not control them and their IPs could’ve changed at any time.

And so I wrote this little script intended to run once in a while from root cron to see if the IPs have changed and to update /etc/hosts as needed. I am almost certain there was a way for me to actually fix this problem instead of working my way around it, but so many unwatched episodes…

You can grab the script here or copy it from below.

#!/bin/bash
# Resolve domain IP and update /etc/hosts as needed. This can be useful if
# DNS lookup is slow and you have a process that keeps looking up the same
# domains over and over again. But, at the same time, you don't want to just
# replace the domain name with a static IP that may change at some point in the
# future. Ugh...

configure() {
  tt="$(date +'%Y-%m-%d_%H%M%S')"
  f="/etc/hosts"
  DIG="$(which dig 2>/dev/null | head -1)"
  declare -a ad=('domain1.com' 'domain2.com' 'domain3.com')
}

verify() {
  if [ ! -f "${f}" ] || [ ! -w "${f}" ]
  then
    echo "File ${f} cannot be opened for writing. Exiting..."
    exit 1
  fi

  if [ -z "${DIG}" ] || [ ! -x "${DIG}" ]
  then
    echo "Unable to find the 'dig' utility. Please install 'bind-utils'. Exiting..."
    exit 1
  fi
}

ip_check() {
  for fqdn in $(printf '%s\n' ${ad[@]})
  do
    ipo=$(grep -m1 -E "\b${fqdn}\b" "${f}" | awk '{print $1}' | grep -m1 -oE "([0-9]{1,3}\.){3}([0-9]{1,3})")
    ipn=$(grep -m1 -oE "([0-9]{1,3}\.){3}([0-9]{1,3})" <(${DIG} +short ${fqdn}))
    if [ -z "${ipo}" ] && [ ! -z "${ipn}" ]
    then
      /bin/cp -p "${f}" "${f}_${tt}"
      echo -e "${ipn}\t${fqdn}" >> "${f}"
    elif [ ! -z "${ipo}" ] && [ ! -z "${ipn}" ]
    then
      if [ "${ipo}" != "${ipn}" ]
      then
        /bin/cp -p "${f}" "${f}_${tt}"
        sed -i "s/${ipo}/${ipn}/g" "${f}"
      fi
    fi
  done
}

# RUNTIME
configure
verify
ip_check