# Increment number of a dns zone



## clinty (Mar 6, 2009)

Hello.

I'm looking for a solution to add a subdomain to a domain zone. The 'problem' is for increment zone number.

If it does not contains the date of today, I replace it by yyyymmdd01. This case is easy.

However, if it contains the date of today, I must replace by the same date, and increment the two last numbers. If number was 2009030603, I must replace by 2009030604.

Any ideas for this case? What tools must I use?

Thanks!


----------



## DutchDaemon (Mar 6, 2009)

A shell script with grep, awk, cut, sed, expr. Or a perl script. I'm sure there are scripts on the net for something this common.


----------



## DutchDaemon (Mar 6, 2009)

Sometimes I indulge in filthy dirty shell script hacks .. 

Call it 'cereal' and call the zonefile as (e.g.)

cereal db.testnet.net


```
#!/bin/sh

# Copyright: whatever!
# Don't bug DutchDaemon!

# read zonefile from cmd
zone=$1
# get serial number
serial=$(grep 'serial no' $zone | awk '{print $1}')
# get serial number's date
serialdate=$(echo $serial | cut -b 1-8)
# get today's date in same style
date=$(date +%Y%m%d)

# compare date and serial date
if [ $serialdate = $date ]
then
# if equal, just add 1
newserial=$(expr $serial + 1)
else
# if not equal, make a new one and add 00
newserial=$(echo $date"00")
fi

# edit zonefile in place, leaving a backup (.bak)
# experiment with amount of tabs (whitespace) needed to line up correctly
sed -i .bak "s/.*serial no.*/                   $newserial      ; serial no./" $zone

# show diffs
diff $zone $zone.bak

# bump zone
/usr/sbin/rndc reload $zone

exit 0
```

Test with old serial:


```
# cereal db.testnet.net
4c4
<                       2009030600      ; serial no.
---
>                       2009022300      ; serial no.
```

Test with a serial of today:


```
# cereal db.testnet.net
4c4
<                       2009030601      ; serial no.
---
>                       2009030600      ; serial no.
```
No guarantee, no beauty


----------



## clinty (Mar 6, 2009)

DutchDaemon said:
			
		

> Sometimes I indulge in filthy dirty shell script hacks ..
> 
> Call it 'cereal' and call the zonefile as (e.g.)
> 
> ...


Wa... Great thank you!
I didn't test it yet, but I read it. Just a point:

```
# get serial number
serial=$(grep 'serial no' $zone | awk '{print $1}')
```

You take the serial by grep a 'serial no' string. This method depends on comments, so if we write 'Serial number', it won't work. Indeed, I do not write any comments in my master zone


----------



## DutchDaemon (Mar 6, 2009)

Sure, you'll have to adapt it to the way you do things, though the '; serial no.' comment in zonefiles is pretty stock BIND syntax. As long as you have a unique string to "grep on to" it should be easy.


----------



## clinty (Mar 6, 2009)

```
# get serial number
serial=$(grep 'serial no' $zone | awk '{print $1}')
```

I think this grep is better... On this script, it's better to grep the serial no than a string/comment.


```
grep -e '2[0-9]\{9\} ${zone}
```


----------



## DutchDaemon (Mar 6, 2009)

That should work for another 991 years, yes. It works for the sed part as well. Well, only if you use date-related serial numbers, of course. There are a lot of people using Unix seconds as a serial instead of a date.


----------



## clinty (Mar 6, 2009)

clinty said:
			
		

> No, that should work for 2xxx years. There's a '2'. I don't have 1xxx years, or 3xxx years. I believe...



--------
DutchDaemon:

It should work for years starting with a 2, so until the year 3000[010100]. Which is, i believe, about 991 years away.

(oops, sorry, edited your post instead of replying to it -- well, it's clear what we mean ...)


----------



## clinty (Mar 10, 2009)

I copy you a version modified for my needs.


```
# vars
ZONEPATH=/etc/namedb/master

# check args
if [ ! $# -eq 1 ]; then
        echo "Usage $0 domain.tld"
        exit 1
fi

# read zonefile from cmd
ZONE=${ZONEPATH}/${1}

# check the file
if [ ! -f ${ZONE} ]; then
        echo "Error: zone does not exist"
        exit 1
fi

# get serial number
SERIAL=$(grep -e "2[0-9]\{3\}[0-1]\{1\}[0-9]\{1\}[0-3]\{1\}[0-9]\{1\}[0-9]\{2\}" ${ZONE} | awk '{print $1}')

# get serial number's date and number
SERIAL_DATE=$(echo ${SERIAL} | cut -b 1-8)
SERIAL_NUMBER=$(echo ${SERIAL} | cut -b 9-10)

# get today's date in same style
DATE_TODAY=$(date +%Y%m%d)

# compare date and serial date
if [ "${SERIAL_DATE}" = "${DATE_TODAY}" ]
then
        # if equal, just add 1
        # if equal and number equal 99, do not change
        if [ ${SERIAL_NUMBER} -ge 99 ]; then
                NEWSERIAL=${SERIAL}
        else
                # increment serial number
                NEWSERIAL_NUMBER=$(expr $SERIAL_NUMBER + 1)
                # if < 10, add a 0 to have 2 digits
                if [ ${NEWSERIAL_NUMBER} -le 9 ]; then
                        NEWSERIAL_NUMBER="0"${NEWSERIAL_NUMBER}
                fi
                # construct new serial
                NEWSERIAL=${SERIAL_DATE}${NEWSERIAL_NUMBER}
        fi
else
        # if not equal, make a new one and add 00
        NEWSERIAL=$(echo ${DATE_TODAY}"01")
fi

# write the new serial
/usr/bin/sed -i -e "s/${SERIAL}/${NEWSERIAL}/g" ${ZONE}

#ok
exit 0
```

If you have advices or comments...


----------



## DutchDaemon (Mar 10, 2009)

Looks fine. Small glitch:

        # if not equal, make a new one and add *00*
        NEWSERIAL=$(echo ${DATE_TODAY}"*01*")


----------



## vivek (Mar 16, 2009)

I've something as follows:

```
#!/usr/local/bin/bash
ZROOT=/etc/named/zones/e
ZFILE=$ZROOT/zone.$1
S=$(grep Serial | awk '{ print $1}' ${ZFILE} )
N=$(( S++ ))
sed -i -e "s/${S}/${N}/g" ${ZFILE}
```
My serial is in following format:

```
2009012202
```


----------

