☰
DNS解析排查实战:从dig、nslookup到systemd-resolved的完整命令指南
2026/10/20 5:36:47 网站建设 项目流程

排查域名解析问题,几乎是每个做运维、开发甚至是搞网络的人每天都要面对的事情。域名解析命令说多不多,说少不少,真正熟练的人能用一套组合拳快速定位问题,而刚入门的朋友常常只会用ping和nslookup,结果域名解析出了问题反而越查越糊涂。这篇文章不打算做教科书式科普,而是从实际干活的角度,把解析域名相关的命令掰开揉碎,讲清楚每个工具到底适合什么场景、输出怎么看、排查故障的时候先敲哪条、后敲哪条,以及我在实操过程里踩过的那些坑。

1. 先搞明白:域名解析这件事到底在做什么

1.1 从“输网址”到“打开网页”,中间发生了什么

你在浏览器输入www.example.com,按下回车,浏览器首先要做的不是连服务器,而是先问系统:“这个域名对应的 IP 地址是多少?” 这个“把域名翻译成 IP”的动作,就是域名解析。

整个过程可以简化成一条链路:你的程序 → 系统解析器(resolver) → 配置的 DNS 服务器 → 根服务器 → 顶级域服务器 → 权威服务器。实际查询时,本地系统通常会先查 hosts 文件,再看本地 DNS 缓存,最后才把请求发给配置的 DNS 服务器。这也是为什么有时候我们已经把域名解析配置改了,但本地还是旧 IP——缓存没过期而已。

理解这条链路非常重要。因为绝大部分“解析域名”的命令,本质都是在帮你模拟或者触发这条查询链路中的某一个环节,比如查缓存、查指定 DNS 服务器、查权威服务器。你用的命令不同,看到的视角也不同。如果不懂这个区别,就容易出现“我明明查了,为什么结果不对”的困惑。

1.2 理解递归查询和迭代查询的区别,排查才有方向

再往深一层说,DNS 查询有两种主要模式。

第一种是递归查询。你问本地的 DNS 服务器(比如运营商的、或者127.0.0.53这种系统自带的解析器):“帮我查www.example.com的 IP”,这个服务器会负责把整个链路跑完,替你去问根、问顶级域、问权威,最后把最终结果拿回来告诉你。你只管要结果,过程是它的事。

第二种是迭代查询。你自己直接去问权威服务器,或者指定一台 DNS 服务器作为查询入口,让你看到每一步的应答。dig的默认行为就有点像“把你的查询请求直接发给指定服务器”,而nslookup则更依赖系统默认的解析器。

为什么要区分这些?因为排查故障的时候,你可以用这种区别来快速圈定问题范围:

  • 全世界的电脑都解析不出来 → 怀疑域名配置、注册商那里的 NS 记录、权威服务器本身。
  • 只有你的电脑解析不出来 → 怀疑本机 hosts、缓存、本地 DNS 服务或者网络。
  • 内网解析有问题、公网没问题 → 怀疑内网 DNS 服务器、防火墙、转发规则。

下面会反复提到这个概念,它直接决定了你该敲哪条命令、该看哪个字段。

2. 常用命令速查:你手边应该有这几把“刀”

2.1 ping:最常被误用的“解析工具”

很多人排查网络第一个反应就是ping 域名。ping本身其实是用来测试网络连通性的,发送的是 ICMP 数据包,它确实会做域名解析,但这只是它顺带干的事。

特点也很明显:能解析,但给的信息极少,只会显示“正在 Ping ... [IP 地址]”,如果解析失败就报“找不到主机”。你没法指定用哪台 DNS 服务器去解析,也没法控制查询哪种记录类型,更没法定制超时时间。

所以我的建议是:ping可以用来快速确认“这域名现在能不能通”,但不要拿它当解析工具来用。尤其是在写自动化脚本的时候,千万别用ping的输出去解析 IP,因为不同操作系统对ping的输出格式差异很大,而且 ICMP 被禁用的主机比比皆是——那并不代表域名解析失败,只是不允许 ping 而已。

如果你真的要快测一个域名解析是否正常,可以这样用:

ping -c 1 www.example.com

看到返回的 IP 之后,心里大概有个数。但接下来要深入查,就要换工具了。

2.2 nslookup:跨平台老牌命令,够用但不是最好用

nslookup算是最普及的解析命令了,Windows、大多数 Linux 发行版上都自带,用户量极大。它有两种模式:非交互式和交互式。

非交互式非常直接:

nslookup www.example.com

输出大概是这样的:

Server: 10.0.0.1 Address: 10.0.0.1#53 Non-authoritative answer: Name: www.example.com Address: 192.0.2.1

这里信息其实不少。“Server”是你当前用的 DNS 服务器;“Non-authoritative answer”意思这个结果不是从权威服务器直接得到的,可能是缓存的。对于日常确认“能不能解析、解析到哪个 IP”,够用了。

指定 DNS 服务器查询:

nslookup www.example.com 8.8.8.8

这样就能绕过系统配置的 DNS,直接向8.8.8.8发查询。排查“到底是本机 DNS 配置问题还是域名本身问题”的时候,这条命令非常实用。

但nslookup的短板也很明显:对各类 DNS 记录的友好程度一般,查 TXT 记录、查 SOA 记录时输出比较呆板;而且它的某些输出字段在多个平台之间并不完全一致。我个人的经验是:在 Windows 上应急用nslookup没问题,在 Linux 上我几乎都改用dig。

2.3 dig:Linux 下最强解析排查工具,没有之一

dig(Domain Information Groper)是我日常工作里最依赖的工具。它来自 BIND 软件包,大多数 Linux 发行版都可以直接安装。

最基础用法:

dig www.example.com

输出是结构化的,而且信息量很大,大致包含这么几段:

; <<>> DiG 9.18.x <<>> www.example.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;www.example.com. IN A ;; ANSWER SECTION: www.example.com. 3600 IN A 192.0.2.1 ;; Query time: 23 msec ;; SERVER: 10.0.0.1#53(10.0.0.1) ;; WHEN: ... ;; MSG SIZE rcvd: 80

平时我看的最多的几个字段:

  • status: NOERROR表示查询正常;如果是NXDOMAIN就表示这个域名根本不存在。
  • flags里的aa表示应答来自权威服务器,ra表示递归可用。
  • ANSWER SECTION中的3600是 TTL,也就是这个记录能缓存多久。
  • SERVER告诉你这条结果是谁返回的。

指定服务器查询:

dig @8.8.8.8 www.example.com

指定记录类型:

dig www.example.com A dig example.com MX dig example.com TXT

追查完整过程:

dig +trace www.example.com

这条指令是排查利器,它会从根服务器开始,一级一级把整个查询链路跑给你看。很多时候同事发我“解析有问题”,我第一件事就是用dig +trace看看卡在哪一级。

我几乎不跟人争论 nslookup 和 dig 谁更厉害,但要说排查域名的效率和信息密度,dig 完胜。如果你在 Linux 上做网络相关工作,请优先熟练 dig。

2.4 host:简单直白,适合脚本和快速验证

host也是一条专门的 DNS 查询工具,最大优点就是命令短、输出更紧凑,适合在脚本里当“快速验证”用。

host www.example.com

输出就是一行:

www.example.com has address 192.0.2.1

指定 DNS 服务器:

host www.example.com 8.8.8.8

查 MX 记录:

host -t mx example.com

对大部分人来说,host的精简输出是优点也是缺点:适合一眼看结果,但信息没dig全。在你只想快速确认一个域名到底解析到哪、或者写脚本需要一个简单的退出码判断时,host很好用。注意,在部分新版系统中host不再是默认安装的,比如某些精简版 CentOS 或 Ubuntu 容器里并没有它,需要另外装bind-utils或dnsutils,这点我在后面的踩坑部分细说。

2.5 getent、resolvectl 等系统级命令

除了上面的网络工具,还有几条和系统解析器紧密相关的命令。

getent(get entries)更像是一个“系统数据库查询接口”,它可以查 hosts 数据库,也就是说它不止走 DNS,还会自动带上 hosts 文件的内容。

getent hosts www.example.com

输出只有 IP 和域名。它的好处是结果更贴近“当前系统真实解析出来的结果”,因为程序走标准解析库(比如 glibc)时,通常和getent的路径一致。而dig是绕过系统解析库直接发 DNS 包的,不看 hosts 文件。所以在排查“为什么程序解析的 IP 和 dig 查的不一样”时,getent hosts这句话能救命。

resolvectl是 systemd 系发行版(比如较新的 Ubuntu、Debian)中管理 systemd-resolved 的命令。用它可以看到当前系统的 DNS 配置:

resolvectl status resolvectl query www.example.com

resolvectl query的结果和getent类似,是走系统解析器的。如果系统 DNS 配置出问题,比如/etc/resolv.conf被篡改,这两个命令就能反映出来。

再补充一个小但有价值的细节:很多系统上/etc/resolv.conf里的注释写着 “Do not edit”,因为它由 systemd-resolved 或 NetworkManager 动态生成。你去手工改这个文件,重启网络服务后往往就被覆盖了。正确做法是用resolvectl或系统网络管理工具改,这也是我在多次“改了又没生效”之后才总结出来的教训。

3. 实操:一次线上 DNS 故障的完整排查过程

3.1 故障现场

某天下午,同事突然反馈说测试环境的某个内部系统访问不了,浏览器一直报“无法解析服务器的 DNS 地址”,但其他同事都说同样是这套系统,自己本地访问没问题。因为涉及“域名解析命令”,我脑子里立刻有一个判断方向:既然不是所有人都挂,那就先查出现问题的这台机器本身。

当时的现场是这样的:

  • 操作系统是某版 Ubuntu Server;
  • 目标域名是内网应用域名app.internal.example.com;
  • 同一局域网内其他机器访问正常;
  • 只有这一台机器报 DNS 解析失败。

第一个直觉是查系统配置。我执行了:

cat /etc/resolv.conf

看到 nameserver 配置指向了10.0.0.53,看起来没什么问题。然后试了ping,结果“Name or service not known”。再到nslookup:

nslookup app.internal.example.com 10.0.0.53

有意思的是,输出显示从这台 DNS 服务器上正常解析到了 IP。这就很怪了:指定服务器查询能出来,系统默认解析却失败,说明问题并不在 DNS 服务器本身,而是在本机的解析流程上。

3.2 用 dig 进一步定位

我接着使用了dig:

dig @10.0.0.53 app.internal.example.com

结果正常返回。然后再用dig不带@参数,也就是走系统默认的解析路径:

dig app.internal.example.com

这次同样失败。注意到SERVER字段指向的是127.0.0.53#53,这说明系统走的是 systemd-resolved。我进一步执行:

resolvectl status

果然发现,系统里存在多个网络接口,而实际生效的 DNS 配置并不是我预期的那个。具体来说,默认路由对应的接口上,DNS 被设置成了127.0.0.53,而127.0.0.53这个本机解析器又因为上游配置错误,导致查询内部域名时没有走对正确的 DNS 服务器。而nslookup app.internal.example.com 10.0.0.53是绕过了本机解析器,直接问内网 DNS 服务器,所以正常。

到这里,问题范围已经缩小到“systemd-resolved 的上游配置”上。

3.3 修复并验证

修复方法其实不复杂,需要把内部域名的查询请求正确转发到内网 DNS。我使用 systemd 的配置方式,在一个新的配置文件中写入:

[Resolve] DNS=10.0.0.53 Domains=~internal.example.com

然后重启 systemd-resolved 服务,再次测试:

resolvectl query app.internal.example.com

结果正常返回了对应 IP。再访问页面,恢复。

这个案例里,命令使用顺序很典型:

  1. ping快速确认“解析不了”;
  2. nslookup 域名 指定DNS判断问题是否在 DNS 服务器侧;
  3. dig不带 @ 参数,确认系统解析路径;
  4. resolvectl status排查系统级配置;
  5. 通过配置修复,再用resolvectl query验证。

整个过程没有一条命令是多余的。这也是我反复强调“不要只知道一条命令”的原因:解析域名命令是一个工具集,它们互相配合才能定位到真正的问题。

4. 深入记录类型:命令怎么查,结果怎么看

4.1 A 和 AAAA 记录:最基础的映射

A 记录把域名映射到 IPv4 地址,AAAA 记录映射到 IPv6 地址。查询方式:

dig example.com A dig example.com AAAA

看输出时重点看ANSWER SECTION,如果为空,可能是这条记录类型不存在或者域名没配置 IPv6。另外还要注意 “NOERROR但 ANSWER 数量为 0” 的情况,这叫“空应答”,一般在 CDN 或某些特殊配置下会遇到,不代表失败。

A 记录相关的常见问题:本地解析出来的是一个非常旧的 IP、而其他人得到的是新 IP。这种情况我第一反应是查 TTL。TTL 越大,缓存时间越长。旧 IP 大概率是本地缓存还没过期,等 TTL 到期或者清一下缓存即可。

4.2 CNAME、MX、TXT 记录

CNAME 就是别名记录,把www.example.com指向example.com或者其他目标域名。查询:

dig www.example.com CNAME

输出里会有一个目标域名,而不是 IP。注意:CNAME 记录不能和别的记录共存于同一个节点上,这是 DNS 协议的一个硬性规则。你给某个主机名配了 CNAME,就不要再给它配 A 记录,否则部分解析器会行为异常。

MX 记录是邮件服务器的关键:

dig example.com MX

输出的长度字段里带有优先级,数字越小优先级越高。我遇到过邮件发不出去的故障,就是域名 MX 记录被误删或者被改到错误的邮件服务器。此时只要dig example.com MX一眼就能看出问题。

TXT 记录现在越来越常用,尤其是用来做域名所有权验证、SPF/DKIM/DMARC 邮件安全配置。查询:

dig example.com TXT

输出经常是一长串字符串,注意查看引号里的内容是否完整。很多 SPF 配置问题其实是 TXT 记录里少了v=spf1前缀或者引号被截断。

4.3 NS、SOA、PTR 记录:排查的“幕后信息”

NS 记录标识一个域名的权威 DNS 服务器。如果你觉得某域名的解析结果不对,先查:

dig example.com NS

再用上一节说的dig +trace看从根到权威的完整路径,就能发现到底是根服务器那里就指错了,还是权威服务器本身返回了错误数据。

SOA 记录里最关键的是序列号。当你的 DNS 配置改了但没生效,先看权威服务器上 SOA 的序列号和你期望的是不是一致。如果权威服务器返回的序列号已经是最新的,只是本地缓存旧,那问题在缓存;如果权威服务器上的序列号压根没变,那说明配置根本没同步过去。

反解(PTR 记录)则是从 IP 反查域名,主要用在邮件反垃圾、日志分析等场景:

dig -x 192.0.2.1

输出里会有一个PTR记录指向某个域名。查不到通常不一定是故障,也可能是网络管理员没有配置反向解析,但做邮件服务时必须注意,很多邮件服务器会校验来源 IP 的 PTR。

dig example.com SOA

输出里的serial字段是排查同步问题的关键,很多新手容易忽略。记录一下这些字段,遇到问题马上能判断该看哪里。

5. 常见问题与排查技巧实录

5.1 排查思路速查表

结合日常经验,我把最常见的域名解析问题整理成一张速查表:

现象可能原因优先执行命令
所有客户端都解析失败域名 NS 配置错误、权威服务器故障、域名过期dig +trace example.com
只有本机解析失败hosts 文件、本地缓存、systemd-resolved 故障getent hosts 域名
部分地域解析结果不一致CDN 调度、多地区 DNS 缓存dig @8.8.8.8 域名对比dig @本地DNS 域名
系统能解析,但程序报错程序内部缓存、glibc 配置、nsswitchgetent hosts查看系统解析路径
修改 DNS 后不生效解析器缓存、配置文件被覆盖resolvectl flush-caches
邮件服务器反查失败缺少 PTR 记录dig -x 邮件服务器IP
域名能 ping 通但网页不能DNS 解析到老 IP、CDN 问题dig A 域名对比多地结果

当你看到这些问题时,第一反应不是“换个命令试试”,而是想清楚:这个解析结果到底经过了哪几条链路?是本地缓存?是系统解析器?还是 DNS 服务器本身?想清楚这一点,敲命令才有方向。

5.2 踩坑记录:我在这上面栽过的跟头

第一个坑:/etc/resolv.conf被覆盖。

刚工作那会儿,我一次次手动往/etc/resolv.conf里加 nameserver,然后重启网络,配置又变回去了。后来才明白,在许多发行版中它是由 NetworkManager 或者 systemd-resolved 动态管理的。正确办法是通过nmcli改连接配置,或者在 systemd-resolved 的 drop-in 配置文件里写,而不是直接改/etc/resolv.conf。这个坑让我白折腾了两小时。

第二个坑:不同工具默认超时时间不一样。

dig默认超时时间很短,在一个网络状况很差的环境里,dig偶尔会超时,但这不代表 DNS 真的挂了。当时我误判过一次。所以遇到dig超时的时候,不要急着下结论,先加长超时再试一次:

dig +time=5 +tries=2 @8.8.8.8 example.com

第三个坑:只看status: NOERROR就认为万事大吉。

NOERROR只代表查询过程没有报错,不意味着你要的记录一定存在。有时候ANSWER SECTION是空的,或者返回的是一个“无数据”的应答。特别是某些网络环境下,查询被劫持或者被缓存污染时,status也可能是NOERROR,但结果明显不对。要养成看ANSWER数量的习惯,不要只扫一眼头两行。

第四个坑:解析结果没错,但程序就是连不上。

有一次排查了很久,dig返回的 IP 完全正确,但应用报超时。最后发现是应用代码里自己做了 DNS 缓存,而且缓存的是很长时间之前解析出的旧 IP。这个教训就是:域名解析正常不代表应用正常,程序自身缓存、连接池、HOST 硬编码都要排查。getent hosts可以看到和程序一致的系统解析结果,但应用内部的缓存得从日志和配置里找。

第五个坑:混合使用 {粘贴内容};

这里有一个跟命令本身密切相关的点:新版dig默认开启 DNSSEC 验证,如果域名 DNSSEC 部署有问题,dig example.com返回的可能是SERVFAIL。这时你以为是网络问题,其实问题在域名密钥或签名上。可以显式关闭验证看看:

dig +dnssec example.com dig +noadflag example.com

看结果是否差异很大。这个坑在中小公司里特别容易遇到,因为 DNSSEC 配置门槛比普通的 A 记录高不少。

第六个坑:阿里/腾讯/华为等云平台的内网 DNS 与公网解析策略不同。

当域名同时存在于公网和云内网时,同一域名在内网环境和外网环境下解析出的 IP 可以完全不一样。排查“为什么别人解析到的是 10.x 内网 IP,你这里却是 203.x 公网 IP”时,要意识到这是正常的策略分流,而不是解析故障。用dig @内网DNS和dig @8.8.8.8对比,很容易看出差异。

6. 一点个人体会

玩解析域名这些命令玩了这么多年,最大的感受就是:工具真不难,难的是脑海里有没有一张“解析链路图”。你敲dig、nslookup、host的时候,实际上是在不同位置拿手电筒照射这条链路。照的位置不同,看到的东西就不同。与其不停记新命令,不如先把 /etc/hosts、本地解析器、缓存、递归服务器、权威服务器这几个概念彻底吃透。

我个人在实际操作里的习惯是:先getent hosts看系统级解析,再dig @8.8.8.8看公网解析,然后dig +trace看完整链路,最后根据情况查 NS/SOA 判断权威侧状态。这套流程下来,99% 的域名解析问题都能定位到具体环节。

最后再分享一个小技巧:如果你写脚本频繁调用域名解析,别用ping,也别频繁 fork 外部命令,用 Python 的socket.getaddrinfo或者 Go 的net.LookupHost这类系统解析接口。这样解析结果更贴近真实程序行为,性能也好很多。

不管是面试新手还是老运维,能在最短时间里用最少命令定位问题,才是真正把“解析域名命令”玩明白了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询