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.8Google公共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_seq1 ttl119 time25.3 ms 64 bytes from 8.8.8.8: icmp_seq2 ttl119 time24.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 DNS8.8.8.8和8.8.4.4全球最知名响应快Cloudflare DNS1.1.1.1和1.0.0.1以隐私和速度著称阿里云 DNS223.5.5.5和223.6.6.6国内访问速度快114 DNS114.114.114.114和114.114.115.115国内老牌稳定 例如改成nameserver 8.8.8.8 nameserver 1.1.1.1nameserver可以配置多个系统会按顺序尝试。保存并退出在nano中按CtrlX然后按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] DNS8.8.8.8 1.1.1.1 FallbackDNS223.5.5.5 114.114.114.114 #Domains #LLMNRno #MulticastDNSno #DNSSECno #DNSOverTLSno #Cacheno #DNSStubListeneryes #ReadEtcHostsyesDNS是首选服务器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是最“正道”且持久的。通过命令行修改适用于所有环境先查看当前的网络连接名称nmcli connection show找到你正在使用的连接名字可能是“有线连接 1”、“Wired connection 1”或你的Wi-Fi名称。为该连接设置DNS。例如为连接名Wired connection 1设置DNSsudo nmcli con mod Wired connection 1 ipv4.dns 8.8.8.8 1.1.1.1ipv4.dns对应IPv4如果是IPv6则用ipv6.dns。设置DNS获取方式为“手动”避免被DHCP服务器下发的错误DNS覆盖sudo nmcli con mod Wired connection 1 ipv4.ignore-auto-dns yes让配置生效sudo nmcli con down Wired connection 1 sudo nmcli con up Wired connection 1或者直接重启NetworkManager服务sudo systemctl restart NetworkManager通过图形界面修改更直观点击屏幕右上角的网络图标 - “有线设置”或“Wi-Fi设置”。点击你当前连接旁边的齿轮图标。切换到“IPv4”或“IPv6”标签页。将“自动(DHCP)”切换为“手动”。在“DNS”栏中输入你想要的DNS服务器地址用逗号分隔如8.8.8.8, 1.1.1.1。点击“应用”。可能需要断开再重新连接网络。4.4 方法四清除本地DNS缓存有时候问题出在本地缓存了错误的记录。刷新缓存可能立竿见影。如果使用systemd-resolvedsudo systemd-resolve --flush-caches如果使用dnsmasq某些环境会安装sudo systemctl restart dnsmasq更通用的暴力重启法重启systemd-resolved服务本身也会清空其缓存。sudo systemctl restart systemd-resolved4.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.conf然后像方法一那样直接写入nameserver 8.8.8.8等。但这样你就完全绕过了systemd-resolved失去了它的缓存、DNSSEC等功能。5. 疑难杂症与深度排查如果以上“标准疗法”都试过了问题依旧那么可能需要一些更深度的排查。5.1 检查防火墙规则本地防火墙ufw或iptables有可能错误地拦截了DNS查询请求目标端口53。检查ufw状态sudo ufw status verbose确保没有规则阻止53端口的出站请求。DNS查询通常是出站请求。临时禁用防火墙测试仅用于诊断生产环境谨慎sudo ufw disable然后测试DNS解析。如果恢复了说明是防火墙问题你需要添加允许DNS查询的规则。sudo ufw allow out 53/tcp sudo ufw allow out 53/udp sudo ufw enable5.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 tracenetwork ping -c 1 www.baidu.com 21 | 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问题看似小但它是网络应用的基石把它理顺了很多后续的工作才能顺畅进行。