例如在 ubuntu 20.04 LTS 中该/etc/hosts
文件为空:
>>> cat /etc/hosts
127.0.0.1 localhost
ping
仍然适用于 localhost 的任何子域:
>>> ping test.localhost
PING test.localhost(ip6-localhost (::1)) 56 data bytes
64 bytes from ip6-localhost (::1): icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from ip6-localhost (::1): icmp_seq=2 ttl=64 time=0.049 ms
^C
--- test.localhost ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1028ms
rtt min/avg/max/mdev = 0.049/0.053/0.058/0.004 ms
或者:
>>> ping test2.localhost
PING test2.localhost(ip6-localhost (::1)) 56 data bytes
64 bytes from ip6-localhost (::1): icmp_seq=1 ttl=64 time=0.042 ms
64 bytes from ip6-localhost (::1): icmp_seq=2 ttl=64 time=0.063 ms
^C
--- test2.localhost ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 0.042/0.052/0.063/0.010 ms
这答案暗示系统解析器参与其中但事实上这是怎么发生的呢?
如果用另一个值localhost
替换/etc/hosts
,子域名将不再起作用:
>>> cat /etc/hosts
127.0.0.1 testname
>>> ping testname
PING testname (127.0.0.1) 56(84) bytes of data.
64 bytes from testname (127.0.0.1): icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from testname (127.0.0.1): icmp_seq=2 ttl=64 time=0.080 ms
^C
--- testname ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1011ms
rtt min/avg/max/mdev = 0.071/0.075/0.080/0.004 ms
>>> ping new.testname
ping: new.testname: Name or service not known
为什么它适用于 localhost 而其他主机名不行,它是如何实现的?
答案1
Linux(Glibc)上的名称解析使用“名称服务切换”系统,其中每个数据源都有一个单独的模块负责。例如,模块libnss_files
负责读取 /etc/hosts(以及 /etc/passwd、/etc/group),而模块libnss_dns
进行 DNS 查询。同样,还有用于从 LDAP、NIS 甚至 SQL 读取数据的模块。
解析“localhost”以及系统主机名由libnss_myhostname
模块(现在作为 systemd 的一部分)处理。您可以在中看到它/etc/nsswitch.conf
。systemd 捆绑版本还处理“localhost”的子域和特殊名称“_gateway”。
这systemd-已解决程序也有自己的libnss_resolve
nsswitch 模块,直接与守护进程对话(不使用环回 DNS),并且它还复制了 libnss_myhostname 的大部分相同特殊名称处理。