Updated to include a function alternative to the original snippet further down.
First of all, dang, it's been a while... 😅
Anyway, I was trying to find a one-off way to print a list of domains and each domain's main A record's IP address. After a little dig
ing 😉 this is what I ended up with initially.
Snippet
#!/usr/bin/env bash
domains=(example.com example.net example.org)
for domain in "${domains[@]}"; do
echo "$domain : $(dig +short a $domain | tail -n1)"
done
Sample output
example.com: 93.184.216.34
example.net: 93.184.216.34
example.org: 93.184.216.34
Explanation
BASH arrays
I'm sorry to say I don't really know much on the subject; the handful of times I've needed them in scripting, I've had to look up syntax for creating them and then accessing. This article seems to shed some light on the subject though, including how to iterate over array indices instead of only array elements.
dig
command
As someone who comes from primarily being a Windows user (only due to work these days), I kept forgetting about this command. It lets you query any kind of DNS records for a domain.
It's also normally pretty verbose too, but passing it the +short
option cuts down the output. a
also tells it to only query A records.
tail
command
I don't use this one often, but I have used head
quite a bit to pull the first 10+ lines of a file if I was looking for some information stored at the top. This command pulls content from the bottom of a file (or output piped to it in this case).
Function alternative
After digging a bit more and chatting with some local Linux users, I ended up rewriting the above snippet into a function that did the same thing.
#!/usr/bin/env bash
function list_domain_ips() {
while read domain; do
echo "$domain: $(dig +short a $domain | tail -n1)"
done < $1
}
Usage
Example 1: passing a filename
# function call
list_domain_ips example.txt
# example.txt contents
example.com
example.net
example.org
Example 2: passing /dev/stdin
list_domain_ips /dev/stdin <<< "example.com
example.net
example.org"
Explanation
while
instead of for...in
loop
This was simpler because the loop will only run as long as the read
command keeps supplying more input.
Last line of the loop: done < $1
This line is what's passing input to the loop. In this case, it's passing the first argument sent to the function, $1
. If the function had second, third, fourth arguments (ad infinitum), they would be $2
, $3
, and $4
, respectively. The first argument is also a filename containing a multi-line list of domains to check.
Using /dev/stdin
as the argument
This is useful if, even though this function expects a filename, you still want to pass a list directly yourself. This part of the solution I found on a superuser answer. Through testing, I found that a blank line will result in undesirable output (just something I wanted to mention for any BASH beginners on here). To prevent this, the opening and closing quotes do need to be in contact with lines that need to be used in the loop.
Sample output with blank lines
: m.root-servers.net. # opening quote on its own line
example.com: 93.184.216.34
example.net: 93.184.216.34
example.org: 93.184.216.34
: m.root-servers.net. # closing quote on its own line
Besides that minor issue, the output is formatted exactly the same way.
⚠️ Important note: I was told by a local Linux wizard 🧙 by the name of Jās Eckard that /dev/stdin
isn't 100% portable.
Just be aware that using /dev/stdin is not portable across all Un*x. I just read yesterday that it's on Linux and OSX (and even then, symlinks to different files), but not necessarily other Un*x.
I just wanted to include this note from him for reference, in case this doesn't work for a particular user.
Summary
So initially I was iterating over an array of domain names, but the better solution ended up being the function since it takes either a filename or a multi-line list sent through /dev/stdin
(and obviously since it's easier to store and call from CLI).
The old echo
line using a subshell to run the dig
command and piping the output to tail
, and prefixing that output with the domain name itself for reference carried over without needing to be changed.
Thanks for reading, and enjoy! 🐧 💻
Top comments (1)
Well... This article was intended to be a short one with a little bit of explanation... 😅