Wednesday, June 9, 2010

系统里的hostname

1. 修改host name需要reboot吗?
2. host name与/etc/hosts有什么关系呢?
3. gethostname为什么不受/etc/nsswitch.conf的配置?

这三个问题在不了解host name是什么的时候, 比较纠结.

是否要reboot这个问题是最直接让我产生dig这个host name的动力, 还有就是工作中, 碰到一台机器无法使用sudo命令, 于是花时间学习学习.

平时看hostname(3)时, 发现hostname(3)与/etc/nsswitch.conf扯在一起, 这使host name与DNS中的记录纠结在一起. 更是希望了解之间的关系

在找资料的过程中, 本人发现了一个很有意思的方法:
 * Linux kernel与GNU分开.
什么意思呢? 分界是为了把不同时期的产物, 概念之类的分开. 比如: 当你认host name是kernel的一个变量时, 那么它就与DNS中的记录有明显的不同.

gethostname是system call, 它不是glibc的东西, 所以它与glibc中的DNS查询机制(/etc/nsswitch.conf)是扯不上关系的. gethostbyname, gethostbyaddr都是glibc的东西

就算没有glibc的存在, kernel中的host name照样存在!

按上面的方法, 已经可以很清楚地知道host name与/etc/hosts, /etc/nsswitch.conf是没有关系的.

linux kernel提供了实时修改kernel参数的方法, 是无需要reboot内核就可以生效的.  如sysctl(2), 也有CLI的sysctl(3). 也可以修改/proc/sys/kernel下的文件.

在实际中, GNU软件又常常会使用到host name!

在工作中碰到一个这样的问题: 每当运行sudo时shell就hang住!
它被block了吗?
于是使用strace一查, sudo是在等socket的IO. 发现这台机器的DNS請求是发不出去的

为什么sudo需要使用网络呢?
这其实就是程序期望得到FQDN格式的host name的結果.
得到FQDN格式的host name就使得host  name与DNS查询纠结在一起.

通过学习hostname命令的代码, 可以得到hostname -f其实是等同于下面的代码
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>

int main(int argc, char *argv[]){
    char hostname[64];
    if ( gethostname( hostname, sizeof(hostname) ) != 0){
        perror("1");
    }   
    struct hostent * host_struct;
    if ( (host_struct = gethostbyname( hostname )) == NULL ){
        perror("2");
    }   
    printf("%s\n", host_struct->h_name);

}

可以得到这样的信息: 得到FQDN格式的host name, 是需要使用到
1. host name
2. DNS
这就与linux下DNS查询顺序策略有关系(/etc/nsswitch.conf)


python里有一段很明了的代码(来自socket.py):
def getfqdn(name=''):
    """Get fully qualified domain name from name.

    An empty argument is interpreted as meaning the local host.

    First the hostname returned by gethostbyaddr() is checked, then
    possibly existing aliases. In case no FQDN is available, hostname
    from gethostname() is returned.
    """
    name = name.strip()
    if not name or name == '0.0.0.0':
        name = gethostname()
    try:
        hostname, aliases, ipaddrs = gethostbyaddr(name)
    except error:
        pass
    else:
        aliases.insert(0, hostname)
        for name in aliases:
            if '.' in name:
                break
        else:
            name = hostname
    return name

这样还可以解开一个疑问: 为什么/etc/hosts里常常会出现hostname和它的FQDN记录
增加这样的信息在这里, 查hostname的FQDN时就无须通过网络得到, 当然, 的确有需求的话, 也是可以的, 如果牛B的话, 就每台机器有一个全球唯一的域名也没有人说


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.