15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用
07.10.2024

如何在Linux中编辑Hosts文件:完整技术指南

Linux中的`/etc/hosts`文件是一个静态查找表,用于将主机名映射到IP地址,在发送任何DNS查询*之前*由操作系统处理。通过在此文件中添加或修改条目,您可以在每台机器的基础上覆盖特定域名的DNS解析——无需修改DNS服务器、路由器或域名注册商的设置。

此机制由名称服务切换(NSS)控制,配置于`/etc/nsswitch.conf`中。默认的`hosts:`行通常显示为`files dns`,这意味着系统首先查询`/etc/hosts`,然后回退到`/etc/resolv.conf`中定义的DNS解析器。理解此顺序至关重要:如果主机名存在于`/etc/hosts`中,DNS查询将永远不会离开本机。

Hosts文件是什么以及它如何工作

`/etc/hosts`文件完全早于现代DNS系统。在早期ARPANET时代,由斯坦福研究院维护的单一`HOSTS.TXT`文件被分发到每台联网机器。今天的`/etc/hosts`是该概念的直接继承者——一个每个符合POSIX标准的操作系统仍然遵守的本地权威覆盖层。

文件中每个非注释行遵循以下语法:

“`

IP_address canonical_hostname [alias1] [alias2] …

“`

  • 以`#`开头的行是注释,将被忽略。
  • 空白字符(空格或制表符)用于分隔字段。
  • 单个IP地址可以在同一行映射到多个主机名。
  • IPv4和IPv6条目可以共存于同一文件中。

全新Linux安装上的最小默认`/etc/hosts`如下所示:

“`

127.0.0.1 localhost

127.0.1.1 myhostname.local myhostname

::1 localhost ip6-localhost ip6-loopback

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

“`

`127.0.1.1`条目是Debian/Ubuntu特有的,当未分配静态IP时,将机器的FQDN映射到回环地址。删除它可能会破坏依赖主机名解析的`sudo`等工具。

为什么要编辑Hosts文件

使用场景从简单的开发者便利到安全关键的基础设施任务不等:

本地开发和预发布环境

在构建或测试时,将生产域名(例如`myapp.com`)指向`127.0.0.1`或局域网IP,而无需修改实时DNS记录。这是在本地或远程服务器上运行VPS托管环境的开发者最常见的使用场景。

多服务器应用程序测试

将站点迁移到新服务器时,仅在本地机器上将域名指向新服务器的IP。您可以在更新公共DNS记录之前验证新环境是否完全正常运行——从而消除停机风险。

屏蔽恶意或不需要的域名

将域名重定向到`0.0.0.0`(比`127.0.0.1`更适合屏蔽)会导致连接立即失败,而无需等待localhost上的连接被拒绝。`StevenBlack/hosts`等项目将数百万个广告、追踪器和恶意软件域名汇总到单个hosts格式的屏蔽列表中。

容器和微服务网络

在没有自定义DNS解析器的Docker或LXC环境中,容器内部(或主机上)的`/etc/hosts`条目提供轻量级服务发现。Docker的`–add-host`标志在运行时将条目直接注入容器的`/etc/hosts`中。

覆盖分离视图DNS

在内部和外部DNS为同一主机名返回不同记录的企业网络中,hosts文件条目可让您在特定机器上实现确定性控制。

SSL证书验证测试

在预发布服务器上测试新的SSL证书部署时,在`/etc/hosts`中将域名指向预发布IP,可让您在上线前验证完整的TLS握手、证书链和HTTPS重定向行为。

分步指南:如何在Linux中编辑Hosts文件

第一步:打开终端

访问终端模拟器。在桌面发行版上,快捷键`Ctrl + Alt + T`适用于GNOME、KDE和XFCE。在无头服务器上,您已通过SSH处于shell会话中。

确认您当前的用户和权限级别:

“`bash

whoami

id

“`

第二步:备份当前Hosts文件

在修改任何系统文件之前,始终创建带时间戳的备份。通用的`hosts.backup`可能会被意外覆盖;时间戳则是明确无误的:

“`bash

sudo cp /etc/hosts /etc/hosts.bak.$(date +%Y%m%d_%H%M%S)

“`

验证备份是否已创建:

“`bash

ls -lh /etc/hosts*

“`

第三步:检查文件权限和所有权

在编辑之前,确认文件的当前所有权和权限:

“`bash

ls -la /etc/hosts

“`

预期输出:

“`

-rw-r–r– 1 root root 221 Jan 10 09:00 /etc/hosts

“`

该文件应由`root:root`拥有,权限为`644`。如果权限不同,请在继续之前进行调查——全局可写的`/etc/hosts`是一个安全漏洞。

第四步:使用文本编辑器打开Hosts文件

使用nano(推荐大多数用户使用):

“`bash

sudo nano /etc/hosts

“`

使用vim:

“`bash

sudo vim /etc/hosts

“`

使用gedit(GUI,GNOME桌面):

“`bash

sudo gedit /etc/hosts

“`

使用tee进行非交互式/脚本化添加(无需编辑器):

“`bash

echo "192.168.1.50 staging.myapp.com" | sudo tee -a /etc/hosts

“`

`-a`标志将内容追加到文件而不是覆盖它。这是自动化脚本和Ansible playbook最安全的方法。

第五步:添加、修改或删除条目

导航到文件末尾并添加您的条目。严格遵循以下格式规则:

  • 每行一个条目。
  • IP地址在前,然后是一个或多个以空白字符分隔的主机名。
  • 使用`#`内联注释条目以供将来参考。

将域名重定向到本地开发服务器:

“`

127.0.0.1 myproject.local # Local dev – remove before production

“`

将域名指向远程预发布服务器:

“`

203.0.113.45 staging.myapp.com # Staging server – pre-DNS cutover

“`

屏蔽域名(使用0.0.0.0的首选方法):

“`

0.0.0.0 ads.example.com

0.0.0.0 tracker.analytics-provider.com

“`

添加IPv6条目:

“`

::1 ipv6-service.local

“`

将多个别名映射到一个IP(适用于虚拟主机):

“`

127.0.0.1 app.local api.local static.local

“`

第六步:保存并退出编辑器

在nano中:

  • 保存:`Ctrl + O`,然后按`Enter`确认文件名。
  • 退出:`Ctrl + X`。

在vim中:

  • 返回普通模式:`Esc`
  • 保存并退出:`:wq`然后`Enter`
  • 不保存退出:`:q!`然后`Enter`

第七步:验证文件内容

确认您的条目已正确写入:

“`bash

cat /etc/hosts

“`

对于大型hosts文件,使用`grep`查找特定条目:

“`bash

grep "myproject.local" /etc/hosts

“`

检查语法错误——缺少IP或地址格式错误的条目将被解析器静默忽略:

“`bash

sudo python3 -c "

with open('/etc/hosts') as f:

for i, line in enumerate(f, 1):

line = line.strip()

if line and not line.startswith('#'):

parts = line.split()

if len(parts) < 2:

print(f'Line {i} may be malformed: {line}')

"

“`

第八步:刷新DNS缓存

在大多数系统上,对`/etc/hosts`的更改会立即对新连接生效。但是,如果您的系统运行本地DNS缓存守护进程,则必须刷新其缓存才能看到更改。

systemd-resolved(Ubuntu 18.04+,大多数现代发行版):

“`bash

sudo systemd-resolve –flush-caches

sudo systemd-resolve –statistics # Verify cache was cleared

“`

nscd(名称服务缓存守护进程):

“`bash

sudo systemctl restart nscd

“`

dnsmasq:

“`bash

sudo systemctl restart dnsmasq

“`

带dnsmasq插件的NetworkManager:

“`bash

sudo systemctl restart NetworkManager

“`

浏览器独立维护自己的DNS缓存。Chrome和Firefox将DNS记录缓存最多60秒。要清除Chrome的内部DNS缓存,请导航到`chrome://net-internals/#dns`并点击”清除主机缓存”。

第九步:测试解析

使用`getent`而不是`ping`来更可靠地测试NSS解析链:

“`bash

getent hosts myproject.local

“`

`getent`直接查询系统的名称服务切换,遵循`/etc/nsswitch.conf`,并向您显示操作系统解析的确切结果——而不是DNS服务器返回的结果。这是最终测试。

此外:

“`bash

ping -c 3 myproject.local

“`

“`bash

curl -v http://myproject.local

“`

如果`getent`返回正确的IP但`ping`没有,则问题在于网络栈或防火墙,而不是hosts文件。

Hosts文件与DNS:何时使用各自

标准`/etc/hosts`DNS服务器
范围仅限单台机器全网络或全局
传播延迟即时几分钟到48小时(取决于TTL)
需要网络是(用于外部DNS)
可扩展性差(手动,每台主机)优秀(集中管理)
支持通配符是(例如`*.example.com`)
重启后保留是(文件持久化)是(服务器管理)
审计跟踪仅通过版本控制取决于DNS提供商
最适合开发/测试覆盖、屏蔽生产基础设施
IPv6支持
自动化友好一般(文件编辑)高(API驱动)

对于管理多台服务器的团队——例如一批独立服务器——集中式DNS管理始终优于手动分发hosts文件更改。hosts文件是每台机器的工具,而不是基础设施工具。

高级技术和边缘案例

在Apache和Nginx虚拟主机中使用Hosts文件

在单台服务器上使用虚拟主机运行多个网站时,*客户端机器*上的hosts文件必须将域名指向服务器的IP。然后,Web服务器使用`Host:` HTTP标头将请求路由到正确的虚拟主机。hosts文件条目和服务器的虚拟主机配置必须使用相同的主机名。

例如,如果您在带cPanel的VPS上为`myapp.local`配置了Apache虚拟主机,请将服务器的IP添加到本地hosts文件:

“`

198.51.100.10 myapp.local

“`

然后在浏览器中访问`http://myapp.local`。Apache读取`Host: myapp.local`标头并提供正确的站点。

保护Hosts文件免受未授权修改

恶意软件经常以`/etc/hosts`为目标,将合法域名(例如银行网站)重定向到钓鱼服务器。使用`chattr`使文件不可变:

“`bash

sudo chattr +i /etc/hosts

“`

这将阻止即使是root用户的修改,直到明确删除不可变标志:

“`bash

sudo chattr -i /etc/hosts # Remove immutability to edit

“`

检查属性:

“`bash

lsattr /etc/hosts

“`

对Hosts文件进行版本控制

对于团队或复杂的开发环境,使用Git跟踪`/etc/hosts`的更改:

“`bash

sudo cp /etc/hosts ~/dotfiles/hosts

cd ~/dotfiles && git add hosts && git commit -m "Add staging.myapp.com entry"

“`

etckeeper等工具使用Git或其他VCS后端自动对整个`/etc`目录进行版本控制,提供系统文件更改的完整审计跟踪。

Docker和Kubernetes中的Hosts文件

在Docker中,您可以在容器启动时注入hosts文件条目,而无需修改主机系统:

“`bash

docker run –add-host=myservice.local:192.168.1.100 myimage

“`

在Kubernetes中,Pod规范中的`hostAliases`可实现相同的结果:

“`yaml

spec:

hostAliases:

  • ip: "192.168.1.100"

hostnames:

  • "myservice.local"

“`

在容器化环境中工作时,这些方法比修改主机的`/etc/hosts`更为可取。

`0.0.0.0`与`127.0.0.1`屏蔽之争

两个地址都用于屏蔽域名,但它们的行为不同:

  • `127.0.0.1`:将连接路由到本地回环接口。如果本地端口80/443上没有监听任何内容,连接将被拒绝——但操作系统仍会尝试建立连接,导致短暂延迟。
  • `0.0.0.0`:在大多数系统上表示无效目标。连接立即失败,无需尝试TCP握手,在屏蔽大量广告/追踪器域名时可实现更快的页面加载。

对于屏蔽列表使用场景,`0.0.0.0`是技术上更优越的选择。

常见错误和故障排除

编辑后更改未生效:

  • 确认条目语法正确(IP在前,然后是主机名)。
  • 刷新本地DNS缓存(参见第八步)。
  • 检查`/etc/nsswitch.conf`——如果`dns`在`hosts:`行中出现在`files`之前,则DNS会被首先查询,hosts文件对于缓存条目将被绕过。

编辑后出现`sudo: unable to resolve host`错误:

  • 您可能删除或损坏了将机器主机名映射到`127.0.1.1`或`127.0.0.1`的行。立即恢复备份:`sudo cp /etc/hosts.bak.TIMESTAMP /etc/hosts`。

特定应用程序忽略条目:

  • 某些应用程序(特别是使用自定义NSS配置的`getaddrinfo`,或使用静态链接解析器的应用程序)完全绕过`/etc/nsswitch.conf`并直接查询DNS。这在禁用CGO编译的Go二进制文件中很常见。使用`strace -e trace=network yourapp`进行验证。

Hosts文件在本地有效但在Docker容器中无效:

  • 容器网络是隔离的。容器有自己的`/etc/hosts`。如上所述,使用`–add-host`或`hostAliases`。

关键技术要点:决策检查清单

在编辑`/etc/hosts`之前,请完成以下检查清单:

  • 范围检查:此更改是否仅需要在一台机器上进行?如果多台机器需要,请使用DNS或Ansible等工具分发更改。
  • 先备份:在任何编辑之前始终创建带时间戳的备份(`hosts.bak.YYYYMMDD_HHMMSS`)。
  • 使用`0.0.0.0`进行屏蔽:更快的失败,无回环开销。
  • 刷新正确的缓存:在重启错误服务之前,确认您的系统使用的是`systemd-resolved`、`nscd`还是`dnsmasq`。
  • 使用`getent`测试:比`ping`更可靠地确认NSS解析。
  • 保护文件:在生产或安全敏感系统上使用`chattr +i`。
  • 记录您的条目:为每个非默认条目添加内联注释(`# reason – added YYYY-MM-DD`)。
  • 删除临时条目:遗留在生产hosts文件中的开发/测试条目是难以诊断的路由错误的常见来源。

如果您在多个环境中管理开发工作流,请考虑将本地hosts文件管理与正确配置的VPS控制面板设置配合使用,以集中管理虚拟主机并减少每台机器的配置漂移。

对于涉及域名注册和分阶段发布的项目,hosts文件仍然是在DNS传播完成之前对新服务器配置执行完整端到端测试的最可靠方式——在公众看到任何更改之前为您提供零风险验证窗口。

常见问题

编辑`/etc/hosts`需要重启系统吗?

不需要。对`/etc/hosts`的更改会立即对新连接生效。如果您有本地DNS缓存守护进程(`systemd-resolved`、`nscd`或`dnsmasq`),则必须刷新其缓存。浏览器也维护独立的DNS缓存,可能需要手动清除。

为什么我的hosts文件条目在终端中有效但在浏览器中无效?

浏览器独立于操作系统解析器缓存DNS记录。Chrome将记录缓存最多60秒。导航到`chrome://net-internals/#dns`并清除主机缓存,或等待TTL过期。

我可以在`/etc/hosts`中使用通配符吗?

不可以。`/etc/hosts`文件不支持通配符条目。每个主机名必须明确列出。如果您需要通配符解析(例如`*.local`),请使用本地DNS解析器,如`dnsmasq`或`unbound`。

`/etc/hosts`中的最大条目数是多少?

内核或glibc没有强制执行的硬编码限制。但是,对于非常大的文件,性能会下降,因为每次查找都会线性解析文件。包含数万个条目的文件(广告屏蔽列表中常见)可能会给主机名解析增加可测量的延迟。对于大型屏蔽列表,专用DNS沉洞(如Pi-hole)更为高效。

删除`/etc/hosts`中的默认条目安全吗?

不安全。默认条目(`127.0.0.1 localhost`、`::1 localhost`以及机器自身的主机名映射)是系统正确运行所必需的。删除它们可能会破坏`sudo`、本地套接字连接以及依赖回环解析的应用程序。只添加或修改条目;除非有具体且充分理解的原因,否则切勿删除默认条目。

15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用