uze (Update ZoneEdit)
Nombre: uze (Update ZoneEdit)
Autor: Patricio Silva (Pato Silva)
Lenguaje: bash
Licencia: GPL
Dependencias: lynx, awk, md5sum
Propósito: Actualizar los registros A de los servidores dns dinámicos de zoneedit para uno o mas hosts y registrar los sucesos en un archivo de log independiente. Minimiza las actualizaciones haciendo un chequeo previo de la dirección IP pública por lo que es muy eficiente. Posee detección de errores de actualización. No se ejecuta como demonio, debe hacerse la ejecución desde un cron o manualmente, personalmente lo ejecuto desde un cron cada 2 minutos.
Código:
#!/bin/sh
#
# Versión 0.4
# Actualiza los dns dinámicos de zoneedit
# Por defecto toma la configuración del archivo cuyo nombre es pasado como primer parámetro
# Si no se especifica ninguno intentará tomarla de /etc/updatezoneedit.conf
# Si de esto se cuple termina con código de salida 1
CONF="/etc/zoneeditupdate.conf"
test $# -eq 1 && CONF=$1
# Chequea que el archivo de configuracion exista
test -e $CONF || exit 1
. $CONF
# Inicializa
IP='123456789'
LISTO=NO
PID=999999
INIT=0
MD5='123456789'
# Toma la ultima IP y las variables del archivo STATE, si existe
if [ -e $STATE ]; then
. $STATE
IP=$IP_ADDR
# Si LISTO es NO el proceso se está ejecutando, se espera TTL segundos
# y si aún no termino se mata el proceso
if [ +$LISTO = "+NO" ]; then
let AUX=${INIT}+${TTL}
if [ `date +%s` -gt $AUX ]; then
# Hay que matar el proceso
echo `date "+%d %b %r"`"$$ ATENCION: Segun el archivo $STATE el proceso $0 (PID ${PID}) se encuentra aún activo. Lleva demasiado tiempo en ejecucion, terminandolo" >> $LOG
if [ $PID -eq "`pgrep -o $0`" ]; then
kill -9 $PID
else
echo `date "+%d %b %r"`"$$ ATENCION: Imposible matar el proceso $0 (PID ${PID}): El proceso no existe o su nombre no es $0 " >> $LOG
fi
else
echo `date "+%d %b %r"`"$$ El proceso ya se está ejecutando, saliendo" >> $LOG
exit 0
fi
fi
fi
# Obtiene la IP Actual desde dyndns
IP_ADDR=`lynx -dump checkip.dyndns.com | grep "Current IP Address:" | awk '{ print $4}' | grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}'`
# Obtiene el hash md5 del archivo de configuracion
MD5_NUEVO=`md5sum $CONF | awk '{ print $1}'`
# Si la IP publica no se pudo determinar se loguea y se sale
test -z $IP_ADDR && echo `date "+%d %b %r"`"$$ No se pudo determinar la dirección IP actual" >> $LOG && exit 0
# Sobreescribe el archivo STATE
echo 'PID='$$ > $STATE
echo 'INIT='`date +%s` >> $STATE
echo 'IP_ADDR='${IP_ADDR} >> $STATE
echo 'MD5='${MD5_NUEVO} >> $STATE
# Si el archivo de configuracion fue modificado se cambia el estado LISTO a MD5
test +$MD5 != +$MD5_NUEVO && LISTO=MD5
# Chequea si la respuesta de dyndns ha cambiado, si no es asi sale
if [ "$IP_ADDR" = "$IP" -a +$LISTO = '+SI' -a +$MD5 = +$MD5_NUEVO ]; then
echo `date "+%d %b %r"`"$$ La IP pública es: ${IP_ADDR}, no es necesario actualizar registros" >> $LOG
echo 'LISTO=SI' >> $STATE
exit 0
fi
if [ +$LISTO = '+SI' ]; then
echo `date "+%d %b %r"`"$$ La IP pública es: ${IP_ADDR}, es necesario actualizar los registros" >> $LOG
fi
if [ +$LISTO = '+FALLO' ]; then
echo `date "+%d %b %r"`"$$ La IP pública es: ${IP_ADDR}, la última actualización no fue exitosa, forzando la actualización de registros" >> $LOG
fi
if [ +$LISTO = '+MD5' ]; then
echo `date "+%d %b %r"`"$$ La IP pública es: ${IP_ADDR}. \"$CONF\" ha cambiado, forzando la actualización de registros" >> $LOG
fi
ERROR=0
# Actualizaciones
for HOST in ${HOSTS}; do
OUT=`lynx -source -auth=${USER}:${PASSWORD} ${WEB}?host=$HOST`
AUX=$(echo $OUT | awk '{print $2}')
case "$AUX" in
'CODE="200"')
echo `date "+%d %b %r"`"$$ Actualizando ${HOST}: registro actualizado correctamente" >> $LOG
;;
'CODE="201"')
echo `date "+%d %b %r"`"$$ Actualizando ${HOST}: no fue necesario actualizar el registro" >> $LOG
;;
*)
ERROR=1
echo `date "+%d %b %r"`"$$ Actualizando ${HOST}: Falló la actualización del registro" >> $LOG
;;
esac
done
test $ERROR -eq 0 && echo 'LISTO=SI' >> $STATE && exit 0
echo 'LISTO=FALLO' >> $STATE
echo `date "+%d %b %r"`"$$ La actualización no fue exitosa, se forzará la actualización de registros en la próxima ejecución" >> $LOG
exit 1
La ejecución presupone la existencia de un archivo de configuración con un contenido similar al siguiente:
# Archivo de configuracion para actualizar los dns en zoneedit
#
# /etc/zoneeditupdate.conf
#
# Archivo STATE contiene informacion acerca del estado de ejecucion del proceso
# El pid, el momento en que empezo a ejecutarse y la ultima IP conocida
#
# TTL es el tiempo maximo en segundos que el proceso puede estar ejecutandose
# Si el proceso se mantuviera en ejecucion por mas tiempo una nueva instancia del mismo
# asumirá que se encuentra zombie y lo terminará, el valor depende de la cantidad
# de host a actualizar, un valor recomendable es 900 (15 minutos)
#
# LOG es el archivo donde se registraran los eventos
#
# USER y PASSWORD son un usuario y clave de acceso valido en zoneedit
#
# WEB es la direccion a la cual se accedera, autenticandose mediante
# USER y PASSWORD, para actualizar los registros A en el DNS dinamico
#
# HOSTS Es la lista de nombres de dominio, separado por espacios y
# encerrado entre comillas, que se actualizaran
STATE="/home/user/.zoneeditupdate.state"
TTL=900
LOG="/var/log/zoneeditupdate.log"
USER='usuario_zoneedit'
PASSWORD='password_zoneedit'
WEB="http://dynamic.zoneedit.com/auth/dynamic.html"
HOSTS="www.deban.org www.esdebian.org host.dominio.zona"
Ejemplo de uso:
./uze
./uze archivo.confLa ruta al archivo de configuración se pasa como único parámetro, si no fuera así intentará tomar la configuración del archivo /etc/updatezoneedit.conf, si nada de lo anterior se cumple terminará con código de salida 1.
Agregar como comentario que funciona, lo utilizo actualmente y nuca tuve problemas, el propósito para hacerlo fue lo problemático e inestable que me ha resultado ddclient