When performing DNS lookups in terminal environments, the dig +short
command is incredibly useful for automation scripts. However, its behavior with CNAME records creates parsing challenges:
$ dig +short docs.sbonds.org
ghs.google.com. # CNAME record
173.194.69.121 # A record
Common attempts like +noall
or -t A
don't solve the core issue - we still get both record types:
$ dig +noall +short docs.sbonds.org
ghs.google.com.
173.194.69.121
1. The AWK Filter Method
This approach filters IP addresses using regex pattern matching:
dig +short example.com | awk '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/{print}'
2. grep with IP Pattern Matching
A simpler alternative using grep's regex capabilities:
dig +short example.com | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
3. Using dig's +answer with Type Filtering
A more precise DNS-level solution:
dig +noall +answer example.com A | cut -f 5
For domains with multiple A records (like load balanced services):
dig +short example.com | grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort -u
For scripting environments, consider this robust implementation:
#!/bin/bash
get_ip() {
local result=$(dig +short "$1" | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}')
[[ -z "$result" ]] && return 1 || echo "$result"
}
When processing large batches:
- Use
+tcp
for consistent timeout behavior - Consider
+time=1
to prevent hangs - Parallelize lookups with
xargs -P
When performing DNS lookups in scripting scenarios, developers often need clean IP address output without intermediary CNAME records. The standard dig +short
approach presents a common pain point:
$ dig +short docs.sbonds.org
ghs.google.com. # Unwanted CNAME record
173.194.69.121 # Desired IP address
BIND's dig offers several approaches to refine the output:
# Method 1: Explicitly query A records only
dig +short docs.sbonds.org A
# Method 2: Use answer section filtering
dig +noall +answer docs.sbonds.org | awk '$4 == "A" {print $5}'
# Method 3: Reverse lookup (when applicable)
dig +short $(dig +short docs.sbonds.org CNAME) A
For production environments, consider these robust solutions:
# Pipe to grep for IPv4 patterns
dig +short docs.sbonds.org | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
# Using xargs for chained lookups
dig +short docs.sbonds.org CNAME | xargs dig +short A
Here's a complete solution for processing multiple domains:
#!/bin/bash
domains=("docs.sbonds.org" "example.com" "test.example.net")
for domain in "${domains[@]}"; do
ip=$(dig +short "$domain" A | tail -n1)
echo "$domain : $ip"
done
The +tries
and +timeout
flags become crucial when processing many records:
dig +short +tries=2 +timeout=2 docs.sbonds.org A | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'