dig命令全解析:从DNS排查到批量巡检的实战指南

📅 发布时间:2026/10/16 12:45:57
dig命令全解析:从DNS排查到批量巡检的实战指南
你是不是也被“域名解析到底为什么失败”折磨过网站无响应、邮件发不出去、CDN 切到一半第一反应往往是拿 nslookup 查一下或者干脆 ping 一下域名。其实这一类问题最趁手的工具是 dig它能在一秒内告诉你查询的是哪台服务器、返回了什么记录、缓存多久过期甚至能一路追踪从根服务器到权威服务器的完整链路。dig 是 DNS 查询领域使用频率最高的命令行工具没有之一。我平时排查解析慢、解析结果不一致、验证 CDN 切换、检查邮件服务器的 MX 记录基本都靠它。这篇文章不打算讲高深理论而是把 dig 的常用姿势、输出含义、实战技巧和踩坑经验一次性讲透适合运维、开发、测试以及所有需要跟域名解析打交道的人。读完你至少能少踩一半的坑。1. dig 命令是什么为什么排障时总得用上它1.1 先聊 dig、nslookup、host 该怎么选很多朋友一进来就是 nslookup然后这种工具在老教程和 Windows 环境里确实常见。但 nslookup 有个问题输出格式在不同版本之间差异很大而且它的输出不是为脚本化处理设计的想把某个 IP 单独抠出来要写半天 grep 和 awk。早期我用它排障经常被一段莫名其妙的“Non-authoritative answer”带偏思路。host 命令比 nslookup 轻量适合快速看某条单一记录输出一眼就能读完。可问题是信息量太少没有完整的响应头、不显示权威区信息、也不方便指定复杂的查询参数。一旦遇到“为什么这台服务器返回的 TTL 不对”这类需要看上下文的问题host 就不够用了。dig 的优势正好补上这两块短板默认输出带完整的报文头、问题区、答案区、权威区、附加区把一次 DNS 交互完整摆在眼前参数极其丰富可以指定任意记录类型、指定 DNS 服务器、调整超时和重试策略输出格式稳定非常适合写进脚本做批量巡检。简单说如果你要解决问题而不是摸鱼选 dig 就对了。工具信息完整度适合场景不足之处nslookup一般应急快速看一眼输出格式不统一脚本处理头疼host低单条记录快速查询上下文信息太少无法做链路排查dig高完整排障、批量巡检、验证配置初次接触觉得输出段多需要适应1.2 安装与第一个查询dig 的安装很简单。Debian/Ubuntu 这类系统上用apt install dnsutilsCentOS 系列用yum install bind-utilsmacOS 默认自带不需要额外装。Windows 用户我建议直接开 WSL或者用在线 DNS 查询页面纯 Windows 生态下原生没有 dig硬要折腾反而浪费时间。装好之后第一件事就是拿自己最常用的域名试一发dig example.com如果网络正常你会看到一大段输出从QUESTION SECTION到ANSWER SECTION最后还有查询耗时、本地解析服务器地址等统计信息。很多人第一次看到这段输出会有点懵实际上每一行都有明确用途下一节就把这段输出彻底拆开讲。2. dig 输出到底在说什么把每一段都读明白2.1 一次完整查询输出逐段拆解直接看一个典型输出以 example.com 为例$ dig example.com ; DiG 9.18.19 example.com ;; global options: cmd ;; Got answer: ;; -HEADER- opcode: QUERY, status: NOERROR, id: 34567 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;example.com. IN A ;; ANSWER SECTION: example.com. 3600 IN A 93.184.216.34 ;; Query time: 23 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP) ;; WHEN: Fri Jan 10 12:00:00 CST 2025 ;; MSG SIZE rcvd: 56第一行DiG 9.18.19是 dig 自己的版本号基本不用管。真正要看的是 HEADER 里的几个字段status: NOERROR表示这次查询从协议层面是成功的只要这里不是 SERVFAIL、NXDOMAIN就说明 DNS 请求没有在半路被拒绝flags: qr rd ra里的 rd 表示你希望递归查询ra 表示服务器允许递归这两个标志组合起来能反映你用的解析服务器是不是正常工作。再往下是QUESTION SECTION这一行回答的是“我问了什么”example.com、IN大类、A记录类型。很多新手在这里容易忽略一个点如果查询的是域名本身而不是子域末尾会有一个点这是 DNS 根域的缩写表示这是一个完整域名。答案区ANSWER SECTION是真正干活的部分3600是 TTL单位是秒意思是这条记录能被缓存 1 小时最后那列就是目标 IP。AUTHORITY SECTION和ADDITIONAL SECTION很多查询里是空的前者给出权威名字服务器的信息后者是附加信息如 EDNS 参数排障时偶尔会用上。末尾三行也很关键Query time是这次交互的耗时SERVER是真正响应你的服务器地址如果你看到它显示127.0.0.53这类本地地址说明查询先经过了本机 DNS 缓存服务MSG SIZE是响应包大小在做 DNS 放大攻击排查或 MTU 问题分析时这个值值得记录。2.2 TTL 和记录类型搞清楚了排障就成功一半TTL 这个概念我习惯把它理解成“保质期”。一条 DNS 记录被解析服务器拿到后会被缓存 TTL 时长期间再有同样的请求就直接用缓存回答不会去问权威服务器。所有人改解析后发现“没生效”十有八九是还没到 TTL 的保质期旧的记录还在缓存里生效。所以排障时的第一个习惯动作就是先看 TTL。比如你刚把服务器 IP 从 A 改成 Bdig 出来的结果还是 A那先别急着骂配置有问题看看 TTL 还剩多久等缓存自然过期再重新查询。记录类型也是必须掌握的。最常见的几种记录类型作用查询命令示例A域名指向 IPv4 地址dig example.com AAAAA域名指向 IPv6 地址dig example.com AAAACNAME域名别名到另一个域名dig www.example.com CNAMEMX邮件服务器优先级与地址dig example.com MXNS域名由哪些权威服务器负责dig example.com NSTXT任意文本信息常用于验证和 SPFdig example.com TXTSOA区域主服务器与序列号等信息dig example.com SOAPTR从 IP 反查域名dig -x 93.184.216.34刚开始记不住没关系多用几次就条件反射了。关键是要记住查 IP 看 A/AAAA查邮箱优先级看 MX查权限归属看 NS查验证字符串看 TXT。把这张表贴在工位上遇到问题先查对应类型能少走很多弯路。3. 实战日常排障与验证的核心操作3.1 最快拿到干净结果short 与输出裁剪如果说dig 域名是全家福那dig 域名 short就是把全家福裁成证件照。执行dig example.com short结果只剩一行93.184.216.34。这个模式特别适合快速确认“域名到底解析到哪个 IP”也是我写脚本时最常用的方式。如果需要控制输出再精细一点可以用组合参数noall answer意思是不要输出那些注释和附加区只要答案区dig example.com noall answer此时输出比默认精简很多只有一行答案记录既有 TTL 又有 IP拿给同事看不会让对方在一堆 header 里找答案。日常我优先用short快速判断需要把 TTL 也留下来给同事核对时再用noall answer。这里提醒一句short是“尽可能精简”但多记录类型时会输出多行比如同时查 A 和 AAAA输出可能交错。所以在脚本里不要想当然认为short一定只有一行稳妥做法是后面接head -n 1或精确指定类型。3.2 指定 DNS 服务器排查缓存、劫持还是配置没生效默认情况下dig 会读系统的/etc/resolv.conf来选解析服务器。如今很多桌面 Linux 用 systemd-resolved本地会有一个127.0.0.53之类的缓存服务。这时候查出来的结果可能是本地缓存而不是权威答案。想要绕过这层直接指定一台公共解析服务比如 8.8.8.8dig 8.8.8.8 example.com noall answer指定服务器这种操作几乎是每次排障的起手式。第一步先看权威侧是否已经生效第二步再看本地缓存是不是过期。如果8.8.8.8返回的是新 IP而默认查询还是旧 IP那问题就在本地缓存层面跟域名配置无关。更进一步可以并行查两个不同的公共解析服务对比结果是否一致。两边 IP 不同要么是解析被拦截或污染要么是权威服务器之间数据不一致。这个对比操作我在 CDN 灰度切换时常用能快速判断流量是否已经覆盖到了边缘节点。当然也不要只依赖某一家公共解析地址多备一两组地址做交叉验证结论才靠得住。3.3 用 trace 看完整链路把问题甩到具体环节普通查询只看“答案”dig trace则把一次域名解析从根到权威的完整链条都摊开给你看。执行dig trace example.com输出会分几段根服务器先告诉你.com区域由哪些服务器负责然后.com权威服务器再告诉你example.com区域的 NS 是哪几台最后到example.com的权威服务器拿到 A 记录。每一层都会显示耗时和服务器地址。这个参数的价值在于定位分层故障。比如某域名在其他机器上解析正常但在这台机器上始终报 NXDOMAIN拉一次trace就能看出是卡在根服务器、顶级域服务器还是最终权威区。我遇到过一种很隐蔽的情况某个内部的 DNS 服务器把example.com当成不存在的区域直接返回 NXDOMAIN普通查询完全看不出来trace一拉就发现根和顶级域都正常只有最后那台权威域名服务器的问题。注意trace的输出比较长不要直接拿来粘贴到聊天窗口刷屏配合noall answer或者分段记录会更合适。它更适合“自己分析”而不是“汇报结果”。3.4 验证业务记录MX、TXT、CNAME 的实用姿势解析出问题的不只是 A 记录。邮件收发异常时先查 MXdig example.com MX输出里每一行都包含优先级和邮件服务器地址数字越小优先级越高。如果 MX 记录指向的服务器不在你预期内邮件就可能在错误的路线上跑。再往深一层可以查 TXT 记录确认 SPF、DMARC 是否配置正确dig example.com TXTSPF 记录通常是一串以vspf1开头的东西里面列出了允许发信的主机或服务商。如果这一条缺失或写错对方邮件服务器很容易拒收你发出去的信。现在很多域名验证比如 HTTPS 证书的 DNS 验证、企业微信和飞书等平台的归属验证也都是通过 TXT 记录完成的所以TXT几乎是必查项。CNAME 的验证也值得一提。CDN 接入时常常需要把某个子域 CNAME 到服务商提供的域名用 dig 查一下就能看到别名指向dig cdn.example.com CNAME有时候你会遇到 CNAME 嵌套一个别名指向另一个别名再指向最终目标。这种链能查到但不要在生产环境故意构造多级 CNAME 链每一级都增加一次查询延迟还可能踩到 CDN 服务商对深度的限制。4. 进阶技巧批量查询、脚本化和格式控制4.1 批量验证一批域名循环与管道组合拳运维手里通常不止一个域名。每次手动敲一遍 dig既慢又容易漏。批量处理的思路很简单把域名列表放循环里逐个查询再打印结果。for domain in example.com example.net example.org; do ip$(dig $domain short A | head -n 1) echo $domain - ${ip:-NoRecord} done这段脚本的逻辑是对每个域名查 A 记录取第一行 IP如果为空则输出NoRecord。我在检查几十个域名是否被某个 CDN 服务商覆盖时就用这个循环套上服务商域名后缀检查哪些返回了CNAME哪些没有一眼就能定位漏配的域名。更省事的做法是把域名列表放到文件里cat domain_list.txt | while read d; do echo $d - $(dig $d short A | head -n 1) done这里要注意一个坑列表文件里不要留空行否则 dig 会查询一个空域名把结果搞乱。另外如果域名数量很大建议在循环里加一点延时比如sleep 0.5避免短时间大量请求触发解析服务器的限速策略。我自己曾有一个巡检脚本没有控制频率跑到一半被解析服务器连续拒绝后来加上延时就稳定了。4.2 反向解析、指定端口、特殊查询反向解析就是通过 IP 查域名用-x参数dig -x 93.184.216.34输出里会出现 PTR 记录。这个动作在排查邮件服务器反向解析、日志溯源验证来源 IP 时非常关键。反垃圾邮件机制往往会要求发件服务器 IP 的 PTR 记录能和发信域名对应上否则邮件会被判为可疑。指定端口的情况一般在调试内部 DNS 环境时遇到。比如你在本机起了一个监听 5353 端口的测试解析服务就可以用dig 127.0.0.1 -p 5353 example.com默认情况下 dig 是用 UDP 53 端口但某些网络环境会限制 UDP或者你想验证 TCP 查询路径是否正常那就加tcpdig tcp example.com这个习惯能帮你绕过零星 UDP 丢包带来的假超时。不过 TCP 查询的耗时通常比 UDP 高一些开tcp是为了验证不是日常默认姿势。4.3 用参数控制超时重试避免脚本卡死脚本里跑 dig 最怕一件事某台解析服务器一直没有响应脚本卡在那边不动。默认情况下dig 会根据系统配置决定超时和重试次数但在稳定的自动化任务里我必须主动限定这些参数dig time3 tries1 8.8.8.8 example.com shorttime3表示每次尝试等待 3 秒tries1表示只试一次。这样最坏情况 3 秒后直接返回不会拖垮整个巡检流程。如果网络环境不太稳定可以把tries调到 2但不要给太多否则批量任务的时间会被无限放大。还有几个参数也值得记norecurse可以禁止递归查询用来测试权威服务器是否返回非递归响应nssearch会尝试搜索一个域的授权记录short和noall answer前面已经用过了。参数不怕多怕不会组合。写进脚本的参数一定要在真实网络环境里跑几遍再收工别因为一次假超时误报了解析故障。5. 高频问题排查与避坑实录5.1 常见报错速查表现象可能原因处理建议dig: command not found系统没装 dnsutils/bind-utilsDebian 系装 dnsutilsCentOS 系装 bind-utilsstatus: SERVFAIL上游解析服务器无法完成递归查询换公共解析服务重试或检查权威服务器状态status: NXDOMAIN域名本身不存在检查拼写检查 NS 记录是否指向正确服务器Query timed outUDP 被拦截或服务器无响应加tcp重试或换目标 DNS 服务器查到结果和网上说的 IP 不一样本地缓存 / 分区域解析 / 解析被污染用8.8.8.8绕开本地缓存对比多组服务器ANY 查询返回 HINFO 或空结果服务器不响应 ANY 类型请求按具体记录类型查 A、MX、TXT 等解析结果一直不变TTL 太长缓存未过期临时调低 TTL等待旧缓存全部过期再切换这些报错文本我几乎每个都在真实环境里见过。其中最坑的是timed out因为它会伪装成“网络故障”实际上可能只是本地防火墙拦了出方向的 UDP 53。同一台机器上dig 内部DNS域名能通但是dig 公共解析服务超时先怀疑出口防火墙对 UDP 的限制再排查链路。5.2 独家避坑经验我踩过的几个坑第一本地缓存比你想的更顽强。每次改完 DNS 配置别人问“为什么还看到旧 IP”我就先在自己机器上执行一条dig 8.8.8.8 域名 noall answer这一条绕过了本地缓存看到的是权威侧真实状态。确认权威侧已经更新再让客户端清理本地缓存或者等待 TTL 过期问题自然清晰。第二泛解析会骗人。有些域名父域配了一条*.example.com的泛解折你用一个不存在的子域名去查结果照样返回一个 IP。这时候很容易误判成“这个子域名存在”。判断方法很简单查一下这个子域的 NS 或 SOA看有没有专属区域。如果只是靠泛解析顶着的别在它上面做正式环境配置。第三CNAME 不能和同名的其他记录共存。DNS 协议规定如果某条名字是 CNAME那么它下面不能再有 A、TXT 之类的同级记录。很多新手在这里踩雷配了www CNAME后又想给www加 TXT 验证结果验证永远过不了。解决办法是用一个独立的子域做验证或者把验证记录挂在父域上。第四TTL 不调低就切换出了问题很难回滚。正确的灰度姿势是提前至少一个完整 TTL 周期把旧记录 TTL 调低比如从 3600 改成 600等所有缓存节点更新完新 TTL再执行真正的 IP 切换。这样一旦发现新服务器有问题改回旧 IP 后最多 10 分钟就能全量恢复不会让用户等一小时。第五脚本里判断“解析失败”要用完整查询状态而不是只看输出是否为空。dig 域名 short没有输出可能是真的没有记录也可能是网络超时。更稳的写法是if dig 8.8.8.8 $domain time3 tries1 short A /dev/null 21; then echo $domain OK else echo $domain FAIL fi用命令退出码判断至少能把“超时”和“无记录”分开。真要区分到底是 NXDOMAIN 还是超时可以用noall comments输出完整状态后由脚本解析。总之自动化任务的告警条件要足够严谨宁缺勿扰也别漏报。我在实际排障里还有个习惯每周固定跑一次自动化巡检把所有业务域名的 A、MX、TXT、NS 记录存成文件用 diff 对比前一次结果。这个日常动作帮我抓到过一次被供应商悄悄修改的 CNAME 指向也帮我发现过一次因为证书验证原因被动过的 TXT 记录。DNS 这个层面不出问题则已一出问题影响的往往是所有依赖它的业务提前积累基线数据排查效率会完全不一样。