Networking

Unix and Linux network configuration. Multiple network interfaces. Bridged NICs. High-availability network configurations.

Applications

Reviews of latest Unix and Linux software. Helpful tips for application support admins. Automating application support.

Data

Disk partitioning, filesystems, directories, and files. Volume management, logical volumes, HA filesystems. Backups and disaster recovery.

Monitoring

Distributed server monitoring. Server performance and capacity planning. Monitoring applications, network status and user activity.

Commands & Shells

Cool Unix shell commands and options. Command-line tools and application. Things every Unix sysadmin needs to know.

Home » Commands & Shells

Auto-Update /etc/hosts

Submitted by on January 9, 2019 – 4:39 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

 

Print Friendly, PDF & Email

Leave a Reply