Zone file sanity check script

Nate Campi nate at campin.net
Wed Mar 20 17:43:01 UTC 2002


On Wed, Mar 20, 2002 at 05:04:44PM +0000, Jim Reid wrote:
> >>>>> "Martyn" == Martyn Drake <martyn at usenet.drake.me.uk> writes:
> 
>     Martyn> Does anybody have any recommendations or know about any
>     Martyn> pre-written scripts that performs basic sanity checking on
>     Martyn> zone files?  It is all too easy for somebody to forget to
>     Martyn> add a full-stop or use a hash instead of a semi-colon for
>     Martyn> comments which ultimately prevent BIND from loading that
>     Martyn> zone file.
> 
> Try named-checkconf that comes with BIND9. It uses the same zone file
> parsing code that the BIND9 server uses. The tool will catch any
> syntax errors. It won't be able to catch semantic errors like a name
> that's missing a terminating dot. After all how could it really know
> for sure if a trailing dot should or shouldn't be there?

Use named-checkconf for conf files (like named.conf) and named-checkzone
for zone files (which answers your question).

Force each update of the files to use it by wrapping zone edits in a
command like this dirty little bash script. This version is missing an
invocation of named-checkzone when editing named.conf, but that's easy
to add. This script checks the zone file out of RCS before editing it,
and where I use a script like this we use RCS ACLs to control who can
check files in and out. It also reloads the only the zone being edited.
If the file is used for multiple zones, a manual reload of the other
zone(s) or the whole server will have to be done to load them. This is
written for BIND 8 on solaris, modifying for other BIND versions and
OS' is easy.

This isn't particularly pretty, but it is very effective.

#!/usr/bin/bash
#
# for debugging
#set -v
#set -n
#set -x
#set -u

PATH=/usr/local/bin:/usr/bin:/usr/local/sbin

FILE="$1"
DOMAIN_NAME="$2"

check_log() {
	echo ""
	echo ""
	echo "Searching logs for messages pertaining to the zone you just edited,"
	echo "and/or any \"rejected\" messages. You'll have to wait a few seconds."
	echo ""
	echo ""

	# wait 5 secs or we may beat the error to the logs
	sleep 5

	if [ -n "$DOMAIN_NAME" ]; then
		tail -200 /var/adm/messages | grep "$DOMAIN_NAME"
	fi

	tail -200 /var/adm/messages | grep "rejected"

	if [ "$?" -eq "0" ]
	then

	echo "The zone file you edited was probably"
	echo ""
	echo "RRRRR  EEEEEE      J EEEEEEE   CCCCC  TTTTTTTTT EEEEEEEE DDDDD"
	echo "R    R E           J E        C     C     T     E        D    D"
	echo "R    R E           J E       C            T     E        D     D"
	echo "R   R  EEEE        J EEEE    C            T     EEEE     D     D"
	echo "RRRR   E           J E       C            T     E        D     D"
	echo "R   R  E      J    J E        C     C     T     E        D    D"
	echo "R    R EEEEEE  JJJJ  EEEEEEE   CCCCC      T     EEEEEEEE DDDDD"
	echo ""
	echo "Go inspect the zone file and the logs, and fix it now, please"
	echo ""

	fi

	echo ""
	echo ""
	echo "If you didn't get any output run something like: "
	echo "\"tail -200 /var/adm/messages | grep $DOMAIN_NAME"
	echo ""
	echo "If you got the message \"file has not changed\" when reloading,"
	echo "then it's normal to have no log output - the zone wasn't reloaded."
	echo "If you got the message \"Zone not found\" and you're sure this is"
	echo "a live zone on this nameserver, issue the command \"ndc reload\" to"
	echo "reload the nameserver."
	echo ""
}

get_answer() {
	echo ""
	echo -n "Would you like to reload the nameserver?  "
	read ANSWER
	case $ANSWER in
	YES|Yes|yes|y|Y)
		echo ""
		echo "Allright, now reloading zone: $DOMAIN_NAME "
		echo ""
		ndc reload $DOMAIN_NAME
		check_log
        ;;
	NO|No|no|n|N)
		echo ""
		echo "Allright, not reloading"
        ;;
	*)
		echo ""
        	echo "Answer yes or no, chump"
		echo ""
		get_answer
        	;;
	esac

}

check_zone() {
        echo ""
        echo "Checking the zone file for errors BEFORE reloading the name server."
        echo "Look for \"OK\" at the end of the check."
        echo ""
	named-checkzone $DOMAIN_NAME $FILE 
	named-checkzone $DOMAIN_NAME $FILE | grep OK > /dev/null 2>&1

	if [ "$?" -ne "0" ]
	then
		echo ""
		echo "Looks like you have errors. Please fix them."
		echo ""
		exit 1
	fi

	get_answer

        echo ""
}

if [ "$1" = "named.conf" ]
then
	co -l $1 && vi $1 ; ci -u $1 && get_answer
	exit 0
elif [ "$#" -lt 2 ]
then
	DOMAIN_NAME_GUESS=${FILE##db.}
        echo -n "Name of the domain this file is for (hit enter for $DOMAIN_NAME_GUESS): "
        read ANSWER
	DOMAIN_NAME="${ANSWER:=$DOMAIN_NAME_GUESS}"
fi

# meat of the script is here:

co -l $1 && vi $1 ; ci -u $1 && check_zone 
-- 
Nate

When asked                    68% of corporate execs said a corporation
"Who owns the Internet?":     23% said it was Microsoft
                              98% of 6th graders said: no one.



More information about the bind-users mailing list