我试图获取一个连接 PostgreSQL 数据库以在服务器上工作的 perl 脚本。这个脚本神秘地失败了。然后我意识到这localhost
不在/etc/hosts
文件中。
该机器(当前运行 Debian lenny)的文件目前看起来像
127.0.0.1 machinename.domain machinename
xxx.xx.x.xxx machinename.domain machinename
这xxx.xx.x.xxx
是IP 地址。我当前的家用计算机的文件是稍旧的安装(当前运行 Debian freeze)是
127.0.0.1 machinename localhost
127.0.1.1 machinename.domain machinename
我的家用计算机位于路由器后面,不直接暴露于互联网。无论如何,我使用 DSL 并且没有静态 IP 地址。
我/etc
对我的机器进行版本控制(使用 etckeeper)已经有一段时间了,我发现对于这台服务器,一些策划者(可能是我自己)于 2009 年 12 月 17 日进行了以下更改。
-127.0.0.1 localhost
+127.0.0.1 machinename.domain machinename
我之前就想知道为什么这个文件是这样设置的,但答案并不明显。一些问题:
为什么
127.0.1.1
?这可能是 Debian 特有的一段历史。我在网上搜索了一下,发现了一些关于 Gnome 的模糊说法,但几乎没有任何实质内容。该文件是从 Debian 中的哪里设置的模板?
目前是否认为该文件的正确/最佳形式?
行中名称的顺序重要吗?我希望不是。
更一般地说,如何解释为什么这两条线的结构如此?
现在,我想我会将服务器更改/etc/hosts
为
127.0.0.1 machinename.domain machinename localhost
xxx.xx.x.xxx machinename.domain machinename
评论?
答案1
概括
你应该一直拥有
127.0.0.1 localhost.localdomain localhost
就您而言,由于您没有永久 IP 地址,因此您也可以拥有
127.0.1.1 machinename.domain machinename
这条线似乎对于某些应用程序(如 GNOME)是必需的,但实际上可能会导致其他应用程序出现问题!
实际上,您的计算机有两个主机名。
localhost.localdomain
是用于在同一台计算机上运行的两个支持 TCP/IP 的进程之间进行私有通信的名称。
machinename.domain
是用于您的机器和连接到您的机器的机器之间通信的名称。
您总是想要localhost.localdomain
指向127.0.0.1
(::1
如果您使用的是 IPv6)。这样,同一台计算机上的两个 TCP/IP 进程之间的所有通信都将使用lo
(环回)接口,这通常是防火墙(例如 )所允许的iptables
,并且无需担心您的网络是否可用或 DNS 是否正常工作。
某些应用程序(例如 GNOME 1)尝试使用计算机的公共名称来表示所有内容,即使是在与同一台计算机通信时也是如此。这样 GNOME 的一个部分就可以与 GNOME 的另一部分进行通信,即使它运行在网络上的另一台机器上。 (GNOME 中的 N 最初代表“网络”。)
理想情况下,您的计算机名称可以通过 DNS 或其他一些共享数据库获知,其他计算机也可以使用这些数据库来确定您计算机的地址,以便其他计算机上的应用程序可以与您的计算机进行通信。
但是,如果您的计算机名称不在 DNS 中,或者 DNS 无法正常工作,像 GNOME 这样的程序仍然需要一种与自身对话的方式。
/etc/hosts
为了使这项工作有效,有多种修改方法。
最常见的曾经是
127.0.0.1 localhost.localdomain localhost
w.x.y.z machinename.domain machinename
其中w.x.y.z
是您的主网络接口的地址,例如eth0
。
如果您的系统使用静态 IP 地址并且始终处于连接状态,则该方法可以正常工作2。
如果您的系统有动态 IP 地址,则会使用各种脚本进行编辑/etc/hosts
,以包含基于 DHCP 服务器返回的条目。
但是,如果您的系统没有永久的网络连接,您就无法添加这样的条目,因为您没有一个可靠的地址。
于是人们开始做类似的事情
127.0.0.1 localhost.localdomain localhost machinename.domain machinename
或者
127.0.0.1 machinename.domain machinename localhost.localdomain localhost
这样,使用 TCP/IP 的进程仍然可以与同一台计算机上的其他进程通信,即使它们使用计算机名称查找 IP 地址也是如此。
但它破坏了其他应用程序。
例如,dnsdomainname
。
我还记得有一个问题,即只有同一台计算机上的人才能连接到服务器,因为服务器只侦听3 环回设备上的连接。
该程序将获取机器的名称,然后查找名称的地址,并使用找到的第一个地址,并绑定到该网络接口。如果您的计算机名称解析为127.0.0.1
4 个地址,则意味着您认为正在运行的服务machinename.domain
(因此可用于整个网络)实际上仅可用于同一计算机上运行的其他进程。
正如安迪指出的那样,名称的顺序并不重要。试图查找主机名的东西127.0.0.1
会得到第一个名称作为主机的规范/官方/主要名称,但因为它会向前和向后解析,所以我不认为这会导致任何问题,除非有一些/etc/hosts
需要一种格式或另一种格式的自动化编辑工具。
但我认为您应该首先拥有一个完全合格的域名(即包含域名的名称),正如我在/etc/hosts 的格式。
还有另一种类似的格式,使用两行而不是一行,例如
127.0.0.1 localhost.localdomain localhost
127.0.1.1 machinename.domain machinename
这是一个巧妙的技巧,因为lo
的地址确实是127.0.0.1/8
,这意味着网络中的任何地址127
都是环回设备。
我假设使用这种格式,以便需要更改条目的工具machinename.domain
可以在不接触条目的情况下完成此操作127.0.0.1 localhost...
。
但请注意,它仍然会导致machinename.domain
映射到lo
,因此它仍然会导致我提到的问题。
我还刚刚在虚拟机中启动 Fedora 15 并登录到 Gnome 桌面,但我看不到任何 TCP/IP 连接。他们似乎都在使用 UNIX 套接字。因此,也许127.0.1.1
不再需要该条目。
脚注
- 过去就是这样。在我的 Fedora 15 测试机上,它似乎使用 UNIX 套接字而不是 TCP/IP。
- 网络启动之前的系统引导期间除外。
- 真正的“束缚”而不是“倾听”。
- 或任何 127.xxx 地址。
答案2
在我的系统上,我有以下内容/var/lib/dpkg/info/netbase.postinst
:
create_hosts_file() {
if [ -e /etc/hosts ]; then return 0; fi
cat > /etc/hosts <<-EOF
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
EOF
我的netbase版本是4.45。
我希望反向查找 IP 地址时会返回该行的第一个名称,否则我怀疑顺序是否重要。
答案3
我之前就想知道为什么这个文件是这样设置的,但答案并不明显。
从文本文件中添加或删除一行非常容易编写脚本。
编辑文本文件中的一行以添加或删除组件要困难得多。
因此,编写一个运行“hostname -s”和“hostname -f”的脚本非常容易,从 /etc/hosts 中删除 127.0.1.1 并添加一个包含主机名结果的新脚本。
但是编写一个脚本来从包含 127.0.0.1 的行中删除任何主机名(不干扰操作员手动添加的条目),然后将当前主机名添加到 localhost 条目要困难得多。