On 01/10/2017 03:40 AM, Michelle Konzack wrote:
Hello experts,

/me looks over his shoulders wondering who's being addressed.

I do not want to querry the world, but only my own Name Server for CNAME
configured (or not).

Okay.  ONLY use local data.  Check.

Currently I am updating my web administration interface and I have  lost
over the time a script, which queried my Name Server for CNAMES.

Been there, done that. Here, have a drink (of your choice) to wash the bitter taste of lost tools down.

E.g. if I have a physical server <vserver04.tamay-dogan.net> I  like  to
know, which CNAMEs (on MY Name Server) pointing to it as

www.electronica.tamay-dogan.net    IN CNAME    vserver04.tamay-dogan.net

If I'm understanding you correctly, you are wanting to know the name of the RR that has your server as the target of a CNAME. (Correct me if I'm wrong.)

OK, I can grep the whole /etc/bind/master/ directory, but since my  Name
Server is responsable for several 1000 (sub)domains,  the  execution  of
the script takes ages!

Something seems wrong here. Unix is EXTREMELY good at text processing, which is what I think would be best here. (I see no reason to involve DNS at all, besides the obvious data subject.)

A few things jump out at me as I read your script, some of which could have significant impact on performance.

----[tdgetincname]------------------------------------------------------
#!/bin/bash

VSERVER="$1"

LIST=`cd /etc/bind/master/ && find -type f |grep -v -E 
"(.conf|.signed|.private|.key)$" |sed 's|^\./||' |sort`

It looks like you're looking to exclude files that end in .conf or .signed, or .private, or .key.

However, that's not what you're actually asking (e)grep to do. You're really asking (e)grep for any occurrence of conf or signed or private or key with any character before them.

I suspect you meant to escape the periods so that you are looking for the literal strings ".conf" or ".signed" or ".private" or ",key".

grep -v -E "(\.conf|\.signed|\.private|\.key)$"

I'm guessing this will speed things up more than a little bit.

I question why you cd to the /etc/bind/master directory rather than just passing the path to find. (Perhaps it's because find's output then returns the full path, instead of just file names. I think there are other ways to deal with this.)

Why are you excluding the files types that you don't want? I would think that it would be better to include just the files types that you do want. (I'm going to assume that you want .zone files for the rest of this email.)

It looks like you're removing the leading "./" from find's output.

Curious, is sorting the output strictly necessary? Or just a would be nice to have. (I ask because this may be a small performance hit.)

Putting all of that I'd be tempted to try to accomplish the goal of building the list of files differently.

   find /etc/bind/master/ -type f -name '*.zone' | sed 's|.*\/||'

Let find generate a raw list (/etc/bind/master/example.com.zone) and then remove all of the head with sed so that you end up with (example.com.zone).

Q: Do you have all your zone files in one directory, /etc/bind/master, or are they separated in something like /etc/bind/master/$client/$zone? - This would change the RE.

(Sorting the output if you want to.)

for FILE in ${LIST}
do
  RET=`cd /etc/bind/master/ && grep -E "IN CNAME.*${VSERVER}" ${FILE} |sed "s|\.[ 
\t]*IN CNAME.*||"`

I suspect that the first ".*" is desired to deal with various types of white space.

I'm guessing that you are wanting to take grep's output, something like "www.electronica.tamay-dogan.net IN CNAME vserver04.tamay-dogan.net", and turn it into just the owning RR name, "www.electronica.tamay-dogan.net". (Correct me if I'm wrong.)

  if [ -n "${RET}" ]
  then
    echo "${RET}"
  fi

It looks like you are printing the owning RR name /if/ there is a value.

I'm guessing your RET variable will either be zero bytes or a list of one or more owning RR names. (Correct me if I'm wrong.)

done
------------------------------------------------------------------------

Note: If I do not the "cd /etc/bind/master/ &&",
      I exceed the maximum lenght of the commandline.

I'm guessing that you have enough files that your sub-command that populates the LIST variable is too long.

Any ideas how to do this better?

Maybe ...

I think I'd be tempted to do something like the following:

for ZONE in $(find /etc/bind -type f -name '*.zone'); do
awk '($2 == "CNAME" && $3 == "vserver04.tamay-dogan.net."){print $1}' ${ZONE}
done

To me this has a number of advantages:

 - There are no Regular Expressions, which can be slow.
 - awk will deal with the different fields for you.
    - Match *JUST* CNAME records.
    - Match the CNAME target
    - Print the RR name
 - You can pass a fully qualified file to awk.
    - No need to for text manipulation.

This is all very simple text manipulation (filtering), which unix excels at.

I have tested the above code and it "Works for Me" (TM).

However ... there is a potential problem. If you are using abbreviated zone files, you may end up missing the ORIGIN in the output since it's not on the line. I.e. the following zone file:

$ORIGIN electronica.tamay-dogan.net.
www     IN      CNAME   vserver04.tamay-dogan.net.

Similarly you may miss some CNAME's if the target is abbreviated.  I.e.:

$ORIGIN tamay-dogan.net.
www,electronica IN      CNAME   vserver04

About the only (trivial) way that I can see to get around this (type of) limitation is to actually parse the zone data, ...or use a tool that does so for you.

I think it's easiest to cheat and parse the output of a "dig axfr".

for ZONE in $(find /etc/bind -type f -name '*.zone'); do
dig axfr ${ZONE} | awk '($4 == "CNAME" && $5 == "vserver04.tamay-dogan.net."){print $1}'
done

Note that the field numbers change because dig includes the TTL and the protocol type, IN.

Thanks in avance

You're welcome.

I hope I helped.

Good luck.

(Please share what you end up doing.)



--
Grant. . . .
unix || die

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

_______________________________________________
Please visit https://lists.isc.org/mailman/listinfo/bind-users to unsubscribe 
from this list

bind-users mailing list
bind-users@lists.isc.org
https://lists.isc.org/mailman/listinfo/bind-users

Reply via email to