虽然这似乎是一个常见问题解答,但我从来没有找到在 Debian/Ubuntu 上用域名更改主机名的正确方法。
首先,通过将主机名和域名(FQDN)放入/etc/hostname
,像这样,这个和这个,许多“答案”或着作都是错误的,因为
Debian 参考资料说主机名不应该使用 FQDN:
3.5.5。主机名
内核维护系统主机名。运行级别 S 中与“ /etc/init.d/hostname.sh ”符号链接的初始化脚本在引导时(使用hostname命令)将系统主机名设置为存储在“ /etc/hostname ”中的名称。此文件应仅包含系统主机名,而不是完全限定的域名。
此外,从man hostname
,它说,
“
/etc/hosts
通常,这是通过将主机名别名为 FQDN 来设置域名的地方。” 和“FQDN 由短主机名和 DNS 域名组成。除非您使用绑定或 NIS 进行主机查找,否则您可以在 /etc/hosts 中更改 FQDN 和 DNS 域名(它是 FQDN 的一部分)文件。”
好的。以上是我应该做的,但这就是我得到的:
$ cat /etc/hostname
coral
$ head -1 /etc/hosts
127.0.0.1 coral.my.domain.org localhost
$ dnsdomainname
ht.home
$ cat /etc/resolv.conf
domain ht.home
search ht.home
nameserver 192.168.0.1
# after I change it to --
$ cat /etc/resolv.conf
# Fixed resolv.conf file
domain my.domain.org
search my.domain.org
nameserver 192.168.0.1
# everything just gone wrong --
$ dnsdomainname
dnsdomainname: No address associated with hostname
$ hostname -f
hostname: No address associated with hostname
$ hostname -d
hostname: No address associated with hostname
更新
我做了一个跟踪hostname -f
,似乎“没有与主机名关联的地址”错误来自libresolv.so
:
$ strace -o /tmp/strace.log hostname -f
hostname: No address associated with hostname
$ grep -E 'openat|close|No address' /tmp/strace.log
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
close(3) = 0
close(3) = 0
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
close(3) = 0
close(3) = 0
write(2, "No address associated with hostn"..., 35) = 35
任何帮助表示赞赏。
$ uname -rm
5.10.0-6-amd64 x86_64
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux bullseye/sid
Release: testing
Codename: bullseye
您的“FQDN”由不同的程序以两种不同的方式确定:
通过对您的主机名进行“主机”查找(使用通常用于解析 IP 地址的相同 Glibc 函数)并返回产生答案的“规范”域名。
例如,这是带有 flags=AI_CANONNAME 的 getaddrinfo() 将在 ai_canonname 字段中返回的内容,而 gethostbyname() 将在 ht_name 字段中返回的内容。实际上,inetutils
hostname -f
确实会调用 gethostbyname() 并在查找成功时打印结果 ht_name。这可以通过 /etc/hosts 或 DNS 进行处理,因此接下来会发生什么取决于 nsswitch.conf 中列出的模块,依次为:
'files' 模块检查 /etc/hosts 的文字主机名(不附加任何内容)。如果它找到匹配的条目,则该条目的第一个名称是规范名称,其余的是别名。IP 地址被返回但被忽略。
所以你可能有这样的条目:
FQDN 必须放在“规范名称”字段中,但短主机名必须存在于别名中,否则将找不到匹配项。
(实际地址在这里无关紧要,只有条目的存在。但因为 gethostbyname() 仅适用于 IPv4,
hostname -f
将跳过 IPv6 地址的 /etc/hosts 条目,而使用 getaddrinfo(AI_CANONNAME) 的程序将包括这些。)'dns' 模块对给定的主机名进行 DNS 'A' 查询,并结合来自 /etc/resolv.conf 的搜索域。因此,使用 hostname
coral
和 resolv.confsearch my.domain.org
,coral.my.domain.org
将进行 A 查找。(如何在 Glibc 中确定搜索域?首先使用 $LOCALDOMAIN,然后使用 resolv.conf 中的“域”或“搜索”,以最后出现的为准,最后检查内核主机名是否包含域。)
无论 DNS 答案中的名称是否具有 A 记录,都将作为规范名称(即您的 FQDN)返回;如果有任何 CNAME,它们的域将作为别名返回。例如,如果查询产生以下结果:
然后
coral.home.domain.net
将是规范名称,左列中的其他两个名称将是别名。(实际返回的 IP 地址仍然无关紧要。关于 gethostbyname() 仅适用于 IPv4 的相同说明。)
其他各种模块,例如“myhostname”或“ldap”或“nis”也可以参与其中。列表中产生答案的第一个获胜。仅当没有模块找到查询结果时,才会返回错误“没有与主机名关联的地址” 。
或者,通过对您的主机名进行“主机”查找,然后对生成的 IP 地址进行反向查找。我认为这不太常见,但仍然发生。
这些是直接的查找,背后没有任何魔法。正向“主机”查找通常使用仅限 IPv4 的 gethostbyname() 完成,返回一个 IP 地址,反之则使用 gethostbyaddr()。
在 /etc/hosts 中,使用 'files' 模块,您将再次需要一个与上面几乎相同的条目 - 将您的 FQDN 作为名字,将短主机名作为同一行中的别名之一。当通过 IP 地址进行反向查找时,将返回名字。
在 DNS 中,使用“dns”模块,正向查找再次与上述相同(搜索域后缀)。
这两个查找是独立的;一个可能通过 /etc/hosts 处理,另一个通过 DNS 等处理。
探索方法#1:
不——它来自 libc 中的高级 nsswitch 代码,在它尝试调用所有启用的模块(首先是 nss_files,然后是 nss_dns→libresolv)并且它们都没有返回答案之后。
他们并非完全错误。Glibc DNS 解析器实际上从您的内核主机名中获取域,并将其用作后备“搜索”域(如果尚未在 resolv.conf 中指定)。
因此它不会立即作为您的 FQDN 返回,但它确实会以与 /etc/resolv.conf 中的
search
或domain
在 /etc/resolv.conf 中完全相同的方式影响该过程。不仅适用于本地 FQDN 查找,还适用于通过 Glibc 函数完成的任何DNS 查找。(参见 resolv/res_init.c 中的函数 domain_from_hostname())