How to Use dig Command to Extract Only IP Address from CNAME Records


1 views

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]+$'