From a single query to a monitoring script
Anyone who only checks DNS records one at a time by hand misses propagation problems and silent changes. Automating DNS lookups with dig and host processes domain lists in seconds, compares resolvers, and catches configuration mistakes before customers report them.
Table of Contents
- 1. Why DNS lookups get automated in Bash
- 2. dig, host and nslookup: the tools at a glance
- 3. Parseable output with dig +short and +noall +answer
- 4. Batch-querying domain lists from files
- 5. Querying specific record types: A, AAAA, MX, TXT, NS
- 6. Comparing DNS propagation across multiple resolvers
- 7. A monitoring script: detecting changes and alerting
- 8. Diagnosing SERVFAIL, NXDOMAIN and timeouts
- 9. dig vs. host vs. getent compared
- 10. Summary
- 11. FAQ
1. Why DNS lookups get automated in Bash
DNS problems are among the most common yet hardest to spot causes of outages: a misconfigured A record, a forgotten MX entry, or a resolver still caching stale values leads to errors that never show up in application code. Anyone automating DNS lookups with dig and host moves this check out of a manual "let me just look" and into a repeatable, documented script.
Especially during domain migrations, hosting provider switches, or the rollout of new subdomains, it is crucial to know the status of many domains at once, not just a single one. A Bash script that automates DNS lookups checks hundreds of domains against multiple resolvers in seconds and delivers a structured overview instead of individual terminal outputs.
Automation also pays off during ongoing operations: DNS entries change less often than application code, but when they do change, the impact is often significant, for example during a CDN switch or a new mail server configuration. A script that automates DNS lookups with dig and host and runs regularly reliably detects such changes long before a user reports a failed email delivery.
2. dig, host and nslookup: the tools at a glance
Three classic tools are available for automating DNS lookups with dig and host in Bash. dig (Domain Information Groper) from the bind-utils or dnsutils package delivers the most detailed and best scriptable output, including explicit options to reduce it to exactly the information needed. host is more concise in its default output and works well for quick, readable one-liners.
nslookup is historically older, considered less consistent across platforms, and is generally no longer recommended for new scripts, though it still shows up in many older tutorials. For Bash automation, dig is the more robust choice because it provides explicit flags for machine-readable output that host and nslookup lack in this form.
#!/usr/bin/env bash
# dns-tools-check.sh — verify dig, host and nslookup availability
set -euo pipefail
for tool in dig host nslookup getent; do
if command -v "$tool" &>/dev/null; then
echo "[OK] $tool: $(command -v "$tool")"
else
echo "[MISSING] $tool not installed"
fi
done
echo "---"
echo "dig version: $(dig -v 2>&1 | head -n 1)"
3. Parseable output with dig +short and +noall +answer
The key to automating DNS lookups with dig and host lies in the right output formatting. dig +short example.com returns only the IP address, without header, question section, or statistics lines, perfect for reading directly into a Bash variable. For more context, but still machine readable, dig +noall +answer example.com returns only the answer section with TTL and record type, without the rest of the noise.
These two modes cover most automation cases: +short for simple existence and value checks, +noall +answer when TTL values or multiple records per domain matter. Anyone who automates DNS lookups with dig and host and wants to process the output further with awk or jq should consistently stick to one of the two formats rather than mixing both in one script.
#!/usr/bin/env bash
# dig-parse-formats.sh — compare short vs. detailed dig output
set -euo pipefail
DOMAIN="${1:-mironsoft.de}"
echo "=== dig +short (only the value) ==="
dig +short "$DOMAIN" A
echo "=== dig +noall +answer (value + TTL + record type) ==="
dig +noall +answer "$DOMAIN" A
echo "=== Extract just the IP with awk from +noall +answer ==="
dig +noall +answer "$DOMAIN" A | awk '{print $NF}'
4. Batch-querying domain lists from files
As soon as more than a handful of domains need checking, a domain list in a text file, one domain per line, combined with a Bash loop pays off. Reading the file robustly matters here too: while IFS= read -r domain; do ... done < domains.txt avoids problems with leading or trailing whitespace and respects comment lines once you filter them out beforehand with grep -v '^#'.
For automating DNS lookups with dig and host at scale, dig also offers the -f option, which processes an entire file of queries in a single dig invocation, which is significantly faster than hundreds of individual process calls in a Bash loop, because only a single connection to the resolver is established.
#!/usr/bin/env bash
# batch-dns-check.sh — check a list of domains for their A record
set -euo pipefail
DOMAIN_FILE="${1:?Usage: batch-dns-check.sh <domain-list-file>}"
declare -A results=()
while IFS= read -r domain; do
[[ -z "$domain" || "$domain" == \#* ]] && continue
ip=$(dig +short "$domain" A | head -n 1)
results["$domain"]="${ip:-NO_RECORD}"
done < "$DOMAIN_FILE"
echo "=== Batch DNS results ==="
for domain in "${!results[@]}"; do
printf '%-30s -> %s\n' "$domain" "${results[$domain]}"
done
# Faster alternative: dig -f processes the whole file in one dig invocation
echo "=== Same result via 'dig -f' (single resolver round trip) ==="
dig +short -f "$DOMAIN_FILE"
5. Querying specific record types: A, AAAA, MX, TXT, NS
Besides the A record for IPv4 addresses, AAAA (IPv6), MX (mail server), TXT (SPF, DKIM, domain verification), and NS (name server) are among the most frequently checked types. Anyone automating DNS lookups with dig and host to, for example, validate an email configuration, specifically queries dig +short example.com MX and checks whether the expected mail server is entered with the correct priority.
For TXT records, which often contain multi-line or quoted values (such as SPF entries like "v=spf1 include:_spf.google.com ~all"), a script must strip the surrounding quotes before further processing the value. dig +short example.com TXT | tr -d '"' is the pragmatic solution here.
#!/usr/bin/env bash
# check-record-types.sh — query multiple DNS record types for one domain
set -euo pipefail
DOMAIN="${1:?Usage: check-record-types.sh <domain>}"
declare -a RECORD_TYPES=(A AAAA MX TXT NS CNAME)
for record_type in "${RECORD_TYPES[@]}"; do
echo "--- $record_type ---"
result=$(dig +short "$DOMAIN" "$record_type")
if [[ -z "$result" ]]; then
echo " (no record)"
else
echo "$result" | sed 's/^/ /'
fi
done
6. Comparing DNS propagation across multiple resolvers
After a DNS change, the immediate question is whether and how quickly it has propagated. Because different resolvers have different TTL caches, a query against the local resolver often returns a different result than a query against a public resolver like Google (8.8.8.8) or Cloudflare (1.1.1.1). Anyone automating DNS lookups with dig and host to check propagation therefore deliberately queries several resolvers with the @resolver-ip option and compares the results.
Such a comparison script immediately shows whether a change has arrived everywhere or whether a particular resolver still returns an outdated, cached value. That is especially valuable for time-critical migrations, where you need to know whether the old or new server is still receiving traffic.
#!/usr/bin/env bash
# propagation-check.sh — compare A record across multiple public resolvers
set -euo pipefail
DOMAIN="${1:?Usage: propagation-check.sh <domain>}"
declare -A RESOLVERS=(
[Google]="8.8.8.8"
[Cloudflare]="1.1.1.1"
[Quad9]="9.9.9.9"
[OpenDNS]="208.67.222.222"
)
echo "=== A record for $DOMAIN across resolvers ==="
for name in "${!RESOLVERS[@]}"; do
ip="${RESOLVERS[$name]}"
result=$(dig +short "@$ip" "$DOMAIN" A | head -n 1)
printf '%-12s (%s) -> %s\n' "$name" "$ip" "${result:-NO_ANSWER}"
done
7. A monitoring script: detecting changes and alerting
A one-time check is not enough for ongoing monitoring. A cron job that automates DNS lookups with dig and host and compares the current value to the last known value detects unauthorized or unexpected changes immediately. The values are stored in a simple file or SQLite database and reconciled on every run.
On a mismatch, the script sends a notification, for example via a Slack webhook or email, and logs the timestamp, old value, and new value. For critical domains whose MX or A records should never change without notice, such monitoring is a simple but effective safeguard against DNS hijacking or accidental misconfiguration by third parties.
| Tool | Output Format | Scriptability | Recommendation |
|---|---|---|---|
| dig +short | Value only, no extras | Very good | Default choice for Bash scripts |
| dig +noall +answer | Value + TTL + type | Good | When TTL matters |
| host | Compact text line | Harder to parse | For interactive one-liners |
| getent hosts | Local resolver view only | Medium | Check system resolution incl. /etc/hosts |
| nslookup | Inconsistent across systems | Poor | Avoid for new scripts |
Mironsoft
Shell automation, DNS monitoring and deployment infrastructure
Keeping DNS configuration in view, for every domain?
We automate DNS checks for domain migrations, monitor critical records continuously, and alert your team on unexpected changes before customers notice anything.
Migration Checks
Batch queries and resolver comparison for safe domain moves
DNS Monitoring
Regular checks of critical records with change alerts
Error Analysis
Diagnosing SERVFAIL, NXDOMAIN, and propagation delays
8. Diagnosing SERVFAIL, NXDOMAIN and timeouts
Anyone automating DNS lookups with dig and host has to be able to distinguish different error responses to react sensibly in the script. NXDOMAIN means the domain simply does not exist, often a typo or a not-yet-registered domain. SERVFAIL, on the other hand, points to a configuration problem at the authoritative name server, such as a broken DNSSEC signature or an unreachable name server.
A third case, timeouts, usually arises from network problems between the client and the resolver, not from the domain itself. In a Bash script, you check the status via dig ... | grep -q "status: NOERROR" or read the command's return value directly, where dig returns a non-zero exit code on network errors, while an NXDOMAIN still returns exit code 0, because the query itself was technically successful, just without a result.
9. dig vs. host vs. getent compared
The table in section seven shows the key differences, but the context matters too: getent hosts uses the system's local name resolution including /etc/hosts and the configured nsswitch.conf order, while dig and host query the DNS resolver directly by default and ignore local overrides. For debugging applications that go through system resolution (such as PHP with gethostbyname), getent is therefore often more informative than a plain dig call.
For pure DNS diagnostics and automation, dig remains the first choice, because it offers the most fine-grained options for output format, resolver selection, and record type. host still works well for quick interactive checks in the terminal, where readability matters more than scriptability.
10. Summary
Automating DNS lookups with dig and host means moving DNS checks from manual single queries into a repeatable, scriptable tool. dig +short delivers the cleanest output for simple value checks, dig +noall +answer adds TTL and record type, and batch processing with a domain list or dig -f scales to hundreds of domains without manual effort.
For migrations, comparing several public resolvers is decisive for verifying propagation. For ongoing operations, a monitoring script that automates DNS lookups with dig and host and logs changes delivers a simple but effective safeguard against unnoticed DNS misconfiguration and hijacking attempts.
Automating DNS Lookups with dig and host — The Essentials at a Glance
Output Format
dig +short for values, dig +noall +answer for values including TTL and type.
Batch Processing
A domain list plus a while loop, or dig -f for a single resolver round trip.
Propagation
Query several resolvers with @resolver-ip and compare the results.
Error Diagnosis
Cleanly distinguish NXDOMAIN, SERVFAIL, and timeout, each with different causes and reactions.