I need help with...<various>

Hello:

I am trying to come up with a BASH 1-liner (I can't use perl or php scripts, don't ask) to grab the nameservers from a host -t ns <domain> command.

Here's what I have and it's as far as I can get:

host -t ns scallyrootest.com | awk '{print $4}' | sort
ns41.hostforweb.net.
ns42.hostforweb.net.

What I'd love to have is:
IP for scallyroottest.com is <IP> at ns41.hostforweb.net.
IP for scallyroottest.com is <IP> at ns42.hostforweb.net.

by running the 1-liner on mostly CentOS platforms

Please and thank you for your time.

if might be a start:

host -t A -v somedomain.com | grep "ANSWER SECTION" -A 2 | grep "A" | grep -v ";;" ; host -t A -v somedomain.com | grep "AUTHORITY SECTION" -A 2 | grep -v ";;"

outputs:

somedomain.com.        3095    IN      A       xxx.xxx.xxx.xxx
somedomain.com.        3095    IN      NS      ns23.domaincontrol.com.
somedomain.com.        3095    IN      NS      ns24.domaincontrol.com.

All I get from that is:
scallyrootest.com. 14400 IN A 216.246.31.81

There are different versions of host so that might be the explanation. The idea is workable, though; get the verbose (debugging) output and parse out the fields you want. But in any case, to get the name and IP address of the name servers, you will need multiple queries -- one to get the names of the name servers, and another to look up their IP addresses. (Some sites put raw IP addresses in the NS records but this is strongly discouraged.)

I think Ikon misunderstood your question, perhaps because the output format you are suggesting is somewhat misleading (perhaps it should mention that these are the IP addresses of the name servers). The pipeline could be simplified a bit but the request of A records instead of NS records is wrong anyway.

Here's what my version of host prints:

vnix$ host -t ns example.com
example.com             NS      a.iana-servers.net
example.com             NS      b.iana-servers.net

So by taking the third field from that and querying for its address, we get the name server IP addresses:

host -t ns example.com | while read dom ns server; do host -t a $server; done

Dressing it up into the format you want is left as an exercise; it can be done along the same lines.

PS. Please try to think up a helpful thread topic title next time.

era:

thanks! I will use a more descriptive topic line next time.

era:

coreutils-5.2.1-31.7 FWIW... :slight_smile:

host -t ns example.com | while read dom ns server; do dig +short $dom; done
gives me:
208.77.188.166
208.77.188.166

and checking the data because we always do...

dig +short @b.iana-servers.net example.com
208.77.188.166
dig +short @a.iana-servers.net example.com
208.77.188.166

I still have work to do: "Dressing it up into the format you want is left as an exercise" :slight_smile:

Thank you VERY much!

I think you're getting the wrong result somehow; at least for me, b.iana-servers.net is 193.0.0.236 -- you're querying for $dom which is wrong, you should be querying for $server, but there can be other complications, too.

dig and host are not part of coreutils; on Ubuntu, at least, they're in the dnsutils and host packages, respectively, and there's also a separate bind9-host package which I believe contains a different version of host (hence, different output formats; originally host was also part of the dnsutils package, but many people wanted the Bind version, so they split it out).

era:

I THINK 193.0.0.236 is the IP OF the nameserver, not the A record ON the nameserver for example.com:

ping -c 1 b.iana-servers.net | grep '64 bytes' && dig +short @b.iana-servers.net example.com
64 bytes from b.iana-servers.net (193.0.0.236): icmp_seq=1 ttl=51 time=99.8 ms
208.77.188.166

Now I am confused (... or you are :slight_smile:

example.com has two name servers. Their names are b.iana-servers.net and a.iana-servers.net. These are the servers which will tell you the IP address of example.com, should you ever ask for it. The way I understood your question, the IP addresses of the name servers is what you want your script to print.

So, given the input example.com, it should print the IP addresses of a.iana.servers.net and b.iana-servers.net

Or, given the input unix.com, it should look up the name servers for unix.com (ns1.sitesolutions.com through ns4.sitesolutions.com) and print their IP addresses.

Did I not understand you correctly? If so, can you rephrase your question?

era:

I just want to know the A record value for example.com that the nameservers have.

HTH.

So you don't care at all about what the nameservers are? Or you want to query all the authoritative name servers in turn? In the former case, host -t a example.com is all you need. In the latter case, what you have (sort of) makes sense, except your version of the script fails to specify which name server to use (but obviously you know how to use dig @server to do that, or you can use host example.com b.iana-servers.net to specify b.i-s.n as the name server to use; but dig is certainly more scripter-friendly).

#!/bin/sh
host=$1
dig +short ns $host |
while read nameserver; do
  dig +short @$nameserver $host | sed "s/^/IP for $host at $nameserver is /"
done

It's not a one-liner unless your lines have fractal dimensions but I hope that wasn't strictly a requirement.

Using almost every trick in the book, I got it down to the following maintainability nightmare.

d="dig +short"; $d ns $1 | xargs -i sh -c "$d @{} $1 | sed 's/^/IP for $1 at {} is /'"

I bet radoulov could still improve on that.

Era:

Don't make a project out of it. You're starting to sound a little OCD'ish over there. :slight_smile:

It even works on my Ubuntu 8.04 platform. I'm in heaven.
I am struggling with echo'ing "IP for scallyroottest.com is" +"at"
from this command:
host -t ns example.com | while read dom ns server; do dig +short $dom; done but managed this poor example of a coding attempt using the example:

host -t ns example.com | while read dom ns server ; do echo "IP for" $dom "is" "<IP>" "at"; done
but it's still missing the do dig routine.

Not sure if/how it can be done. Can you have >1 do ; done routine?

Short of any clear answers, I am on my way to some serious homework. :slight_smile:

Thanks everyone who pitched in with support....

You can have as many commands as you like between the "do" and "done", and of course, they can be new loops with "do" and "done" in them. Not sure where you'd need that, though. You can simply modify the sed script to shuffle things around in a different order if that's how you like them.

sed "s/.*/IP for $host is & at $nameserver"

The "s/from/to/" command in sed will substitute the stuff in "from" with the stuff in "to" on each line. In this case we are replacing the IP address printed by dig with the longer string. & retrieves the "from" string into the "to" string. Dot star is the regular expression for "everything on this line" (dot means any character, star means any number of times).

Just to show an alternate way of doing it, here's a loop which prints the message piecemeal.

#!/bin/sh
host=$1
dig +short ns $host |
while read nameserver; do
  echo -n "IP for $host is "
  dig +short @$nameserver $host | tr '\n' ' '  # replace final newline with space
  echo "at $nameserver"
done

Or you can interpolate with backticks

  echo IP for $host is `dig +short @$nameserver $host` at $nameserver

Backticks AKA grave accents (ASCII 96) capture the output of one command so you can use it in the command line of another command. Notice that those are not regular single quotes. Copy/paste them if you can't find them on your keyboard.

And here's the answer I wanted with desired output:

host -t ns example.com | while read dom ns server; do dig +short $dom | echo $server "shows an IP of" `dig +short $dom` for $dom; done <enter>

Gives me this output:
server a.iana-servers.net. shows an IP of 208.77.188.166 for example.com
server b.iana-servers.net. shows an IP of 208.77.188.166 for example.com

Thanks era for the assist. :slight_smile:

The pipeline to echo is just discarded; you can take that out.

host -t ns example.com | while read dom ns server; do
  echo $server "shows an IP of" `dig +short $dom` for $dom;
done