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)

3
  • I think that might be better for stackoverflow.com due the programming relevance?
    – djdomi
    Sep 19 at 11:19
  • I am asking about a unix command to resolve DNS. Sep 19 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 at 6:44

4 Answers 4

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
3
  • 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. Sep 21 at 22:14
  • Which is exactly what "rely on your system's name resolution" (i.e. getaddrinfo) means.
    – fuero
    Sep 21 at 22:36
  • I felt obligated to point that out, because the question asked for DNS resolution. Sep 22 at 0: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.

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
0

I think you're looking for

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

or better

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.