主机名区分大小写 - getent 的输出不同

主机名区分大小写 - getent 的输出不同
[root@GFVM4 ~]# hostname
GFVM4
[root@GFVM4 ~]# 
[root@GFVM4 ~]# 
[root@GFVM4 ~]# getent hosts gfvm4
192.168.122.151 GFVM4
[root@GFVM4 ~]# getent hosts GFVM4
fe80::5054:ff:feac:787 GFVM4
[root@GFVM4 ~]# 
[root@GFVM4 ~]# 
[root@GFVM4 ~]# 
[root@GFVM4 ~]# ifconfig ens5
ens5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.122.151  netmask 255.255.255.0  broadcast 192.168.122.255
        inet6 fe80::5054:ff:feac:787  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:ac:07:87  txqueuelen 1000  (Ethernet)
        RX packets 452  bytes 33008 (32.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 204  bytes 26112 (25.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@GFVM4 ~]# 

以上是预期的行为吗?

正如您所见,我已设置全部大写的 HOSTNAME GFVM4。

如果我使用相同的名称(全部大写),它将返回 ipv6 地址。如果我使用小写字母的主机名,它将返回 ipv4 地址。

这是正确的行为吗?

将 Fedora21 作为基于 qemu 的 VM 运行。

谢谢

答案1

这不是一个完整的答案,只是想分享我的发现,而且它太长了,无法容纳在评论中......

首先,如果您想回复,getent您需要在、、等中进行正确的配置。/etc/nsswitch.conf/etc/resolv.conf/etc/hosts一个 Fedora 22,它在中有以下几行/etc/nsswitch.conf

hosts:    files mdns4_minimal [NUTFOUND=return] dns myhostname

getent hosts localhostgetent hosts LOCALHOST给出了不同的结果。但是当我改为 之后/etc/nsswitch.confhosts: files它们给出了相同的结果。

我认为当您有多个来源进行搜索时,他们可能会以不同的方式处理案例并给出不一致的结果。

其次,您可能想尝试getent ahost。它使用getaddrinfo()而不是gethostbyname2()。至少在我的例子中,它给出了更一致的答案。参见man getent

第三,我发现阅读源代码很有趣获取客户端并通过 观察跟踪ltrace getent hosts localhost。您可以在那里看到inet_pton()gethostbyname2()。您还可以通过 跟踪系统调用ltrace -S,并可以看到打开了哪些文件,例如/etc/hosts

以下是 的输出ltrace。在 AF_INET (2) 之前尝试 AF_INET6 (10)。

[a@localhost ~]$ ltrace getent hosts LOCALHOST
__libc_start_main([ "getent", "hosts", "LOCALHOST" ] <unfinished ...>
mtrace()                                                                                                     = <void>
setlocale(LC_ALL, "")                                                                                        = "en_US.UTF-8"
textdomain("libc")                                                                                           = "libc"
argp_parse(0x606440, 3, 0x7ffc1cf8a7c8, 0)                                                                   = 0
strcmp("hosts", "hosts")                                                                                     = 0
inet_pton(10, 0x7ffc1cf8c67a, 0x7ffc1cf8a680, 0)                                                             = 0
inet_pton(2, 0x7ffc1cf8c67a, 0x7ffc1cf8a680, 0x658e2f20)                                                     = 0
gethostbyname2(0x7ffc1cf8c67a, 10, 0x7ffc1cf8a680, 0x658e2f20)                                               = 0
gethostbyname2(0x7ffc1cf8c67a, 2, -20, 0x7f166586c8f5)                                                       = 0x7f1665b16260
inet_ntop(2, 0xc47000, 0x7ffc1cf8a620, 46)                                                                   = 0x7ffc1cf8a620
printf("%-15s %s", "127.0.0.1", "localhost.localdomain")                                                     = 37
__overflow(0x7f1665b13620, 32, 0, 0x7fffffda)                                                                = 32
fputs_unlocked(0xc47041, 0x7f1665b13620, 0x7f1665d36025, 0xfbad2a84)                                         = 1
__overflow(0x7f1665b13620, 10, 0xc47050, 0x74736f686c61636f127.0.0.1       localhost.localdomain localhost
)                                                 = 10
+++ exited (status 0) +++

最后,我的建议是 1)控制来源getent/etc/nsswitch.conf或 2)维护自己的数据库/词典。

答案2

只是猜测,但从http://linuxmanpages.net/manpages/fedora21/man1/getent.1.html

hosts 当没有提供密钥时,使用 sethostent(3)、gethostent(3),
                    和 endhostent(3) 枚举主机数据库。当
                    提供一个或多个关键参数,将每个键传递给
                    gethostbyaddr(3) 或 gethostbyname2(3),取决于
                    对 inet_pton(3) 的调用是否表明密钥是
                    是否为 IPv6 或 IPv4 地址,并显示结果。

http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/usr.bin/getent/getent.c“if (argc == 2)” 表示“% getent hosts”(未提供键),因此执行以下操作:

    for (i = 2; i < argc; i++) {
        if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
            he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
        else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
            he = gethostbyaddr(addr, INADDRSZ, AF_INET);
        else
            he = gethostbyname(argv[i]);
        if (he != NULL)
            hostsprint(he);
        else {
            rv = RV_NOTFOUND;
            break;
        }
    }

我不擅长 C 语言,而且我通过快速谷歌搜索找到的唯一来源是 NetBSD,但似乎如果第一个 inet_pton(http://linuxmanpages.net/manpages/fedora21/man3/inet_pton.3.html) 找到 IPv6 的条目,则跳过 IPv4 的第二个函数。此外,乍一看,我没有看到任何强制大小写(这意味着区分大小写似乎不是强制的)。

也就是说,GFVM4 可能有 2 个条目,一个在上,另一个在下。上一个条目可能与 IPv6 地址相关联。

如果您能针对不同情况下的不同条目提供确认或不确认信息,以便确认(或不确认),那就太好了。如果确认,我会说这是 getent 软件的预期行为。

相关内容