1. 问题初探:当你的Ubuntu突然“失联”
你有没有遇到过这种情况?在Ubuntu终端里,无论是想用apt update更新一下软件源,还是想ping一下百度看看网络通不通,屏幕上突然弹出一行刺眼的错误:Temporary failure resolving ‘archive.ubuntu.com’或者Name or service not known。那一刻,感觉就像你的电脑突然变成了信息孤岛,明明网线插着,Wi-Fi连着,但就是“找不到北”。
这个“Temporary failure resolving”错误,说白了就是DNS解析临时失败。DNS,你可以把它想象成互联网的“电话簿”或“导航仪”。当你想访问“www.baidu.com”时,你的电脑并不知道这个好听的名字对应着哪个IP地址(比如14.215.177.39)。它需要去问DNS服务器:“嘿,老兄,‘百度’家怎么走?” DNS服务器查一下自己的通讯录,然后把正确的IP地址告诉你,你的电脑才能找对门。如果这个问路的过程失败了,你就得到了这个报错。
这个问题在Ubuntu上其实挺常见的,尤其是刚装完系统、从虚拟机克隆出来、或者切换了网络环境(比如从公司网换到家里网)之后。它不一定是网络硬件坏了,更多时候是系统里负责“问路”的那套配置(也就是DNS客户端)出了点小状况。作为一个常年和Linux服务器、开发环境打交道的人,我处理过无数次这类问题。今天,我就把这个问题的来龙去脉、排查思路和几种最有效的解决方法,掰开揉碎了讲清楚,让你下次再遇到时,能从容应对,快速“修复导航”。
2. 核心原理:DNS是如何工作的,以及它为何会“临时失败”
要解决问题,先得理解问题背后的机制。这样你才能举一反三,而不是死记硬背几个命令。
2.1 DNS解析的简易流程
当你执行ping www.baidu.com时,你的Ubuntu系统内部会发生一系列连锁反应:
- 本地缓存查询:系统首先检查自己的“短期记忆”(DNS缓存),看看最近是不是问过这个地址。如果有记录且未过期,就直接使用,速度最快。这个缓存可能由
systemd-resolved、dnsmasq或nscd等服务管理。 - 读取静态配置:如果缓存没有,系统就会去读取“导航设置文件”——
/etc/resolv.conf。这个文件里写着默认的DNS服务器地址,比如nameserver 8.8.8.8。系统会向这个地址发起查询。 - 发起递归查询:你的电脑向
8.8.8.8(Google公共DNS)提问:“www.baidu.com的IP是啥?” 如果8.8.8.8自己也不知道,它会替你去向更高级的DNS服务器(根域名服务器、顶级域服务器等)一层层问下去,直到拿到答案,再返回给你。 - 结果返回与缓存:拿到IP地址后,系统不仅会用这个地址去通信,还会把它存入本地缓存一段时间,方便下次快速访问。
2.2 “Temporary Failure”的常见病因
所谓“临时失败”,就是指这个查询流程在某个环节卡住了,但并非永久性故障。主要原因有以下几类:
- DNS服务器地址不可达或无效:
/etc/resolv.conf里配置的DNS服务器IP本身是错的,或者那个服务器宕机了、网络不通。比如有些网络环境会分配特定的内网DNS,如果你配置成了公网DNS,可能就无法解析内网域名。 - DNS客户端服务异常:Ubuntu上负责管理DNS解析的核心服务(如
systemd-resolved)没有运行,或者运行状态不正常(卡死、崩溃)。 - 网络管理器配置冲突:如果你使用了NetworkManager或netplan来管理网络,它们可能会动态覆盖
/etc/resolv.conf文件。如果网络管理器的配置有问题,或者与手动修改的resolv.conf冲突,就会导致解析失败。 - 本地DNS缓存污染:本地缓存里存了错误的或过期的记录,导致系统拿到了一个无效的IP地址。
- 防火墙或网络策略限制:有些网络环境(如公司、学校)会限制对外部DNS服务器(如
8.8.8.8)的访问,只允许使用指定的DNS服务器。如果你的配置不符合策略,请求就会被拦截。 /etc/resolv.conf文件属性问题:这个文件有时是一个指向其他地方的符号链接(symlink),并且被设置为不可更改(immutable)。如果你试图直接编辑它,可能无法保存。
注意:在开始任何修复操作前,一个非常好的习惯是先
ping一个公网IP地址,比如ping 8.8.8.8。如果这个能通,说明你的基础网络连接(物理层、IP层)是没问题的,问题百分百出在DNS解析层面。如果不通,那你首先要解决的是网络连通性问题(比如网卡驱动、IP地址获取、网关配置等),那将是另一个话题了。
3. 诊断流程:一步步定位问题根源
遇到问题不要慌,按照以下步骤排查,可以快速锁定问题所在。请打开你的终端,我们一步步来。
3.1 第一步:检查基础网络连通性
就像前面说的,先确认你能“走出家门”。
ping -c 4 8.8.8.8如果看到类似下面的输出,说明网络通路是好的:
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=119 time=25.3 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=119 time=24.9 ms ...如果完全不通(100% packet loss),请先解决你的IP地址、网关、路由等基础网络配置问题。
3.2 第二步:检查当前的DNS配置
这是最关键的一步。查看系统当前正在使用哪些DNS服务器。
cat /etc/resolv.conf你会看到类似这样的内容:
# This is /etc/resolv.conf. nameserver 127.0.0.53 options edns0 trust-ad search localdomain或者
nameserver 8.8.8.8 nameserver 8.8.4.4重点观察nameserver行:
127.0.0.53:这是一个本地回环地址。这表明你的系统正在使用一个本地的DNS转发服务(通常是systemd-resolved)。你的所有DNS查询会先发到这个本地服务,再由它转发到真正的上游DNS服务器。这是一种现代且常见的配置。- 具体的IP地址(如
8.8.8.8):这表明系统被配置为直接使用某个公共或指定的DNS服务器。
同时,注意文件开头的注释。如果它写着# Generated by NetworkManager或# This file is managed by man:systemd-resolved(8),说明这个文件是被某个网络管理工具自动生成的,直接编辑它可能无效,重启后会被覆盖。
3.3 第三步:测试DNS解析功能
使用nslookup或dig命令来专门测试DNS解析。dig命令功能更强大,信息更详细,如果系统没有,可以用sudo apt install dnsutils安装(前提是你能暂时用IP地址搞定apt,比如暂时修改sources.list为IP地址形式,或使用其他方法)。
测试1:使用系统当前配置的DNS服务器
dig www.baidu.com看输出的ANSWER SECTION部分,如果有返回IP地址,说明解析成功。同时注意输出最末尾的SERVER:一行,它显示了本次查询实际使用的DNS服务器地址,可以和/etc/resolv.conf里的对比一下。
测试2:指定一个公认可靠的DNS服务器进行测试
dig @8.8.8.8 www.baidu.com这条命令是绕过系统配置,直接向Google的DNS服务器8.8.8.8发起查询。如果这个能成功,而第一步不指定服务器的dig失败,那就铁定是你系统自身的DNS配置出了问题。
3.4 第四步:检查DNS解析服务状态
如果你的/etc/resolv.conf指向了127.0.0.53,那么本地DNS转发服务systemd-resolved的状态就至关重要。
systemctl status systemd-resolved.service查看服务是否是active (running)状态。如果服务没启动或失败了,这就是问题的根源。
4. 解决方案大全:从易到难,总有一款适合你
根据上面诊断出的不同原因,我们可以采取相应的解决措施。建议按顺序尝试。
4.1 方法一:最快捷的临时修复——修改/etc/resolv.conf
如果诊断发现/etc/resolv.conf里的DNS服务器地址明显错误或无效(比如是一个不存在的内网地址),而文件又不是被严格管理的,可以临时修改它。
- 备份原文件(好习惯):
sudo cp /etc/resolv.conf /etc/resolv.conf.backup - 使用文本编辑器(如nano)编辑文件:
sudo nano /etc/resolv.conf - 将
nameserver行替换为可靠的公共DNS服务器。常用推荐:- Google DNS:
8.8.8.8和8.8.4.4(全球最知名,响应快) - Cloudflare DNS:
1.1.1.1和1.0.0.1(以隐私和速度著称) - 阿里云 DNS:
223.5.5.5和223.6.6.6(国内访问速度快) - 114 DNS:
114.114.114.114和114.114.115.115(国内老牌稳定) 例如,改成:
nameserver 8.8.8.8 nameserver 1.1.1.1nameserver可以配置多个,系统会按顺序尝试。 - Google DNS:
- 保存并退出(在nano中按
Ctrl+X,然后按Y确认,再按Enter)。 - 立即测试:
ping www.baidu.com
实操心得:这个方法通常是临时的。因为如果系统使用了NetworkManager或
systemd-resolved,它们可能会在下次网络连接重置时,用自己管理的配置覆盖掉你手动修改的/etc/resolv.conf。所以,如果这个方法生效了,但重启网络或电脑后又失效,说明你需要用下面更持久的方法。
4.2 方法二:针对systemd-resolved服务的修复(现代Ubuntu首选)
从Ubuntu 18.04 LTS开始,系统默认使用systemd-resolved来管理DNS。它提供了一个本地DNS解析器(监听在127.0.0.53),并管理着上游DNS服务器列表。
情况A:服务未运行如果systemctl status显示服务未运行,启动它:
sudo systemctl start systemd-resolved.service sudo systemctl enable systemd-resolved.service # 设置为开机自启情况B:服务运行正常,但上游DNS配置错误我们需要修改systemd-resolved的全局DNS配置,这才是持久生效的地方。
- 编辑其主配置文件:
sudo nano /etc/systemd/resolved.conf - 找到
[Resolve]部分,修改或添加DNS和FallbackDNS行。取消行首的#注释,并填入DNS服务器地址。[Resolve] DNS=8.8.8.8 1.1.1.1 FallbackDNS=223.5.5.5 114.114.114.114 #Domains= #LLMNR=no #MulticastDNS=no #DNSSEC=no #DNSOverTLS=no #Cache=no #DNSStubListener=yes #ReadEtcHosts=yesDNS是首选服务器,FallbackDNS是备用服务器。 - 保存文件后,重启
systemd-resolved服务以使配置生效:sudo systemctl restart systemd-resolved.service - 检查
/etc/resolv.conf,它现在应该是一个指向/run/systemd/resolve/stub-resolv.conf的符号链接,并且内容中的nameserver是127.0.0.53。这才是正确的状态。 - 验证新的DNS是否生效:
在输出中,你应该能看到你刚配置的systemd-resolve --status | grep -A5 "Global"DNS Servers。
4.3 方法三:针对NetworkManager的修复(桌面版常用)
如果你使用的是Ubuntu桌面版,图形化网络通常由NetworkManager管理。通过它来设置DNS是最“正道”且持久的。
通过命令行修改(适用于所有环境):
- 先查看当前的网络连接名称:
找到你正在使用的连接,名字可能是“有线连接 1”、“Wired connection 1”或你的Wi-Fi名称。nmcli connection show - 为该连接设置DNS。例如,为连接名
Wired connection 1设置DNS:sudo nmcli con mod "Wired connection 1" ipv4.dns "8.8.8.8 1.1.1.1"ipv4.dns对应IPv4,如果是IPv6则用ipv6.dns。 - 设置DNS获取方式为“手动”(避免被DHCP服务器下发的错误DNS覆盖):
sudo nmcli con mod "Wired connection 1" ipv4.ignore-auto-dns yes - 让配置生效:
或者直接重启NetworkManager服务:sudo nmcli con down "Wired connection 1" && sudo nmcli con up "Wired connection 1"sudo systemctl restart NetworkManager
通过图形界面修改(更直观):
- 点击屏幕右上角的网络图标 -> “有线设置”或“Wi-Fi设置”。
- 点击你当前连接旁边的齿轮图标。
- 切换到“IPv4”或“IPv6”标签页。
- 将“自动(DHCP)”切换为“手动”。
- 在“DNS”栏中输入你想要的DNS服务器地址,用逗号分隔,如
8.8.8.8, 1.1.1.1。 - 点击“应用”。可能需要断开再重新连接网络。
4.4 方法四:清除本地DNS缓存
有时候问题出在本地缓存了错误的记录。刷新缓存可能立竿见影。
- 如果使用
systemd-resolved:sudo systemd-resolve --flush-caches - 如果使用
dnsmasq(某些环境会安装):sudo systemctl restart dnsmasq - 更通用的暴力重启法:重启
systemd-resolved服务本身也会清空其缓存。sudo systemctl restart systemd-resolved
4.5 方法五:处理顽固的/etc/resolv.conf符号链接问题
如果你发现/etc/resolv.conf是一个指向/run/systemd/resolve/stub-resolv.conf的蓝色高亮文件(符号链接),并且你想直接控制它,可以采取以下步骤:
- 首先,删除现有的符号链接:
sudo rm /etc/resolv.conf警告:执行此操作前,请确保你知道自己在做什么,或者已经用方法二配置好了
systemd-resolved。删除后如果什么都不做,系统将完全没有DNS配置。 - 然后,创建一个指向
systemd-resolved真实上游DNS列表的符号链接(推荐),或者创建一个普通的静态文件。- 推荐方案:链接到真实解析文件
这个文件(sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf/run/systemd/resolve/resolv.conf)包含了systemd-resolved从各种渠道(配置文件、DHCP等)收集到的真实上游DNS服务器,而不是本地的127.0.0.53。这样,应用程序会直接使用上游DNS,但依然受systemd-resolved管理。 - 备选方案:创建静态文件
然后像方法一那样,直接写入sudo nano /etc/resolv.confnameserver 8.8.8.8等。但这样你就完全绕过了systemd-resolved,失去了它的缓存、DNSSEC等功能。
- 推荐方案:链接到真实解析文件
5. 疑难杂症与深度排查
如果以上“标准疗法”都试过了,问题依旧,那么可能需要一些更深度的排查。
5.1 检查防火墙规则
本地防火墙(ufw或iptables)有可能错误地拦截了DNS查询请求(目标端口53)。
- 检查
ufw状态:
确保没有规则阻止53端口的出站请求。DNS查询通常是出站请求。sudo ufw status verbose - 临时禁用防火墙测试(仅用于诊断,生产环境谨慎):
然后测试DNS解析。如果恢复了,说明是防火墙问题,你需要添加允许DNS查询的规则。sudo ufw disablesudo ufw allow out 53/tcp sudo ufw allow out 53/udp sudo ufw enable
5.2 检查/etc/hosts文件
系统在查询DNS前,会先查看本地的/etc/hosts文件。如果这个文件里有一条记录错误地将某个域名指向了一个错误或不可达的IP,也会导致问题。
cat /etc/hosts检查是否有异常的、你不认识的关于常见域名(如archive.ubuntu.com)的条目。通常,这个文件里只应该有127.0.0.1 localhost这样的基本条目。
5.3 使用strace进行高级追踪(终极武器)
如果所有方法都无效,可以使用strace命令追踪一个简单命令(如ping)执行时,所有系统调用的过程,看看它到底卡在哪一步。
strace -f -e trace=network ping -c 1 www.baidu.com 2>&1 | grep -iE '(socket|connect|sendto|recvfrom)'这个命令会过滤出与网络相关的系统调用。你可以看到程序试图连接哪个地址和端口。如果连connect到DNS服务器(如8.8.8.8:53)的调用都没有出现,说明问题可能在更早的配置读取阶段;如果connect失败了,会显示错误原因(如Network is unreachable)。
5.4 虚拟机或容器的特殊考虑
- 虚拟机(如VMware, VirtualBox):确保网络适配器设置为“NAT”或“桥接”模式,并且宿主机的网络是通的。在“NAT”模式下,虚拟机通常使用宿主机的网络和DNS,有时需要检查虚拟网络编辑器的设置。
- Docker容器:容器内的DNS默认继承自宿主机的
/etc/resolv.conf。如果宿主机DNS有问题,容器内也会有问题。你可以通过docker run时的--dns参数,或在docker-compose.yml中指定dns:来为容器单独设置DNS。
6. 最佳实践与预防措施
解决了眼前的问题,我们再来看看如何避免它再次发生。
- 优先使用系统网络管理器:对于桌面用户,尽量通过NetworkManager的图形界面或
nmcli命令来设置DNS。对于服务器,如果使用netplan,则在YAML配置文件中指定nameservers。这是最符合系统设计、最不容易出现冲突的方式。 - 理解
systemd-resolved的角色:在现代Ubuntu上,接受并学会配置/etc/systemd/resolved.conf,而不是总想着去改/etc/resolv.conf。理解stub-resolv.conf和resolve.conf两个文件的不同作用。 - 配置备用DNS:在任何配置中,都至少设置两个
nameserver,一个首选,一个备用。这能在一台DNS服务器故障时提供基本的冗余。 - 区分内外网环境:在公司或学校内网,可能需要使用内网指定的DNS服务器才能解析内部域名(如内部Wiki、GitLab)。在家或公网环境下,则可以使用公共DNS。可以配置NetworkManager为不同的网络连接(Wi-Fi)使用不同的DNS设置。
- 定期检查:在进行大的系统更新、更换网络环境后,可以快速运行一下
dig www.qq.com来验证DNS解析是否正常。
我自己在管理多台服务器和开发环境时,养成了一个习惯:在完成任何新的系统部署或网络变更后,把dig一个外部域名和ping一个外部IP作为“健康检查”的第一步。这两个简单的命令,能帮你迅速将问题定位到“是网络不通”还是“DNS不灵”,从而节省大量盲目排查的时间。DNS问题看似小,但它是网络应用的基石,把它理顺了,很多后续的工作才能顺畅进行。