6

I have a domain name in a bash variable ($TARGET), and I want to get the IPv4 (A record) address of it in my bash script (I also want to get the IPv6 AAAA record (if exists)), in a robust manner.

i.e. What bash/unix command will: (i) print the IP address (and only the IP address) of the DNS resolution (ii) print nothing to stdout (or non-zero exit) if there is no DNS record for that domain found (iii) allow me to choose to ask for A or AAAA record.

host "$TARGET" prints lots of human readable stuff, and I'm reluctant to parse that.

dig +short looked promising, but in some scenarios, it also prints other warning messages which I do not understand, or care about.

$ dig +short -t A "$TARGET"
;; Warning: Client COOKIE mismatch
1.2.3.4

Debian test/bookworm. Bash v5.2 (installed via apt)

Amandasaurus
  • 31,471
  • 65
  • 192
  • 253
  • I think that might be better for stackoverflow.com due the programming relevance? – djdomi Sep 19 '22 at 11:19
  • I am asking about a unix command to resolve DNS. – Amandasaurus Sep 19 '22 at 11:42
  • 3
    Note: there are some subtle differences in how your system can resolve a specific host (i.e. how `/etc/hosts` typically had precedence over DNS). Do you want the same IP that `ping` would send packets to, in other words the results the system resolver finds, or a DNS record, ignoring /etc/hosts and other sources? And how do you want to deal with round-robin/multi-valued records. – diya Sep 20 '22 at 06:44

4 Answers4

11

I'm unsure if you want to actually query nameservers or rather rely on your system's name resolution:

$ getent ahosts one.one.one.one. | awk '{ print $1 }' | sort -u
1.0.0.1
1.1.1.1
2606:4700:4700::1001
2606:4700:4700::1111
$ getent ahosts nonexistent.host | awk '{ print $1 }' | sort -u
$ getent ahosts www.what-is-my-ipv4.com | awk '{ print $1 }' | sort -u
185.26.156.187

You can also make it return v4 or v6 addresses with ahostsv4 and ahostsv6.

If you just use hosts, you are subject to your /etc/gai.conf's settings.

Found this on https://unix.stackexchange.com/questions/212897/nslookup-dig-firefox-ignoring-etc-hosts-file-entries:

nslookup, dig, and host are tools for querying DNS name servers.

If your configuration is not provided by a name server (like the information given in /etc/hosts) those tools will not show them, because they directly ask the name server.

If you want to check that the "usual" resolution is working (i.e. the way specified in /etc/nsswitch.conf) you can use getent:

getent hosts www.winaproduct.com
fuero
  • 9,591
  • 1
  • 35
  • 40
  • Note that `getent hosts` uses your machine's name resolution mechanism, which may or may not be DNS, depending on what is configured in `/etc/nsswitch.conf`. Alternative sources of information could include the `/etc/hosts` file, WINS, and multicast DNS, for example. The information could also be subject to caching mechanisms such as `nscd`. – 200_success Sep 21 '22 at 22:14
  • Which is exactly what "rely on your system's name resolution" (i.e. `getaddrinfo`) means. – fuero Sep 21 '22 at 22:36
  • I felt obligated to point that out, because the question asked for DNS resolution. – 200_success Sep 22 '22 at 00:39
7

You are on the right track with dig. You can suppress that particular cookie related error (per the man page). Below, I am also choosing to redirect all errors to /dev/null just in case, as you wanted failures to be silent.

[jg7@comp1 ~]$ TARGET="google.com"

[jg7@comp1 ~]$ dig +short +nobadcookie -t A "$TARGET" @8.8.8.8 2>/dev/null
64.233.177.139
64.233.177.138
64.233.177.101
64.233.177.113
64.233.177.100
64.233.177.102

[jg7@comp1 ~]$ dig +short +nobadcookie -t AAAA "$TARGET" @8.8.8.8 2>/dev/null
2607:f8b0:4002:c08::65
2607:f8b0:4002:c08::8a
2607:f8b0:4002:c08::64
2607:f8b0:4002:c08::71

If this isn't what you are looking for, then let me know.

[EDIT] Used a bash variable so as to be closer to the original question.

JG7
  • 196
  • 5
7

getent ahosts[v4|v6] and generally anything that uses getaddrinfo() is the right answer, as it will use the same name resolution mechanisms (DNS, mDNS, NetBIOS, NIS, LDAP…) as the rest of the system, as well as performing the same suffix search (i.e. resolv.conf domain) as the rest of the system.

For example, if getent was not available, you could do:

gaiv4="import sys, socket
res = socket.getaddrinfo(sys.argv[1], 0, socket.AF_INET, socket.SOCK_STREAM)
for e in res: print(e[4][0])"
python -c "$gaiv4" serverfault.com

I usually have the ndisc6 package installed for other reasons, and it happens to have name2addr:

name2addr -m -4 www.google.com
user1686
  • 10,162
  • 1
  • 26
  • 42
0

I think you're looking for

    dig +nocomments +short -t A "$TARGET"

or better

    dig +noall +short -t A "$TARGET"
Leo Vdw.
  • 1
  • 1