在/etc/hosts中不映射主机名到环回地址



我使用Vagrant (v1.7.2)来配置Linux (Fedora 22)主机,以及Vagrant -hostmanager插件(v1.6.1)写入/etc/hosts,使主机可以相互访问。

My Vagrantfile:

Vagrant.configure(2) do |config|
  config.vm.box = "workshop"
  config.hostmanager.enabled = true
  config.hostmanager.include_offline = true
  config.vm.define "server" do |server|
    server.vm.network "private_network", ip: "192.168.33.10"
    server.vm.hostname = "server.local"
  end
  config.vm.define "client" do |client|
    client.vm.network "private_network", ip: "192.168.33.20"
    client.vm.hostname = "client.local"
  end
end

当I vagrant up时,server虚拟机有以下/etc/hosts:

127.0.0.1 server.ipademo.local server
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
## vagrant-hostmanager-start
192.168.33.10   server.ipademo.local
192.168.33.20   client.ipademo.local
## vagrant-hostmanager-end

(对于虚拟机client,只在第一行替换s/server/client/ )

因为Vagrant>= 1.5.0在配置之前运行Vagrant -hostmanager插件,我还尝试在配置期间通过将Vagrantfile更改为:

来运行hostmanager
  config.hostmanager.enabled = false
  config.hostmanager.include_offline = true
  config.vm.provision :hostmanager

结果相同。

问题描述

127.0.0.1 <fqdn> <shortname>行与vagrant-hostmanager添加的信息冲突。我需要抑制主机名与环回地址的关联,以便在每个VM上,主机名解析为私有网络地址,如vagrant-hostmanager添加的。

我怎样才能做到这一点?

问题的原因是Vagrant为Fedora客户机提供的更改主机名功能。特别是在plugins/guests/fedora/cap/change_host_name.rb:

def update_etc_hosts                             
  ip_address = '([0-9]{1,3}.){3}[0-9]{1,3}'
  search     = "^(#{ip_address})\s+#{Regexp.escape(current_hostname)}(\s.*)?$"
  replace    = "\1 #{fqdn} #{short_hostname}"
  expression = ['s', search, replace, 'g'].join('@')
  sudo("sed -ri '#{expression}' /etc/hosts")
end

update_etc_hosts方法用新的主机名替换原来的主机名(对于Fedora,这是localhost.localdomain,绑定到环回地址127.0.0.1)。然后用短主机名更新/etc/hostname,尽管系统调用仍然返回完整主机名,因为它出现在/etc/hosts中。

的解决方案

我提供了额外的提供程序(在之后运行,上面描述的黑客行为发生):

  1. 查询长主机名 (FQDN)并将其写回/etc/hostname。在下一步修复/etc/hosts后,hostname --fqdn实际上返回完整的主机名。

  2. 恢复/etc/hosts中的环回行,以便机器的主机名解析为 vag流浪者-hostmanager设置的私有网络地址。

顺序很重要。以下是Vagrantfile代码:

# Vagrant's "change host name" sets the short host name.
# Before we undo the /etc/hosts silliness (see below) let's
# reset /etc/hostname to the *full* host name
#
config.vm.provision "shell",
  inline: "hostname --fqdn > /etc/hostname && hostname -F /etc/hostname"
# Vagrant's "change host name" capability for Fedora
# maps hostname to loopback, conflicting with hostmanager.
# We must repair /etc/hosts
#
config.vm.provision "shell",
  inline: "sed -ri 's/127.0.0.1s.*/127.0.0.1 localhost localhost.localdomain/' /etc/hosts"

当通过vagrant设置主机名时,大多数linux发行版(redhat, debian, arch等)都有由change_host_name vagrant功能引起的相同问题。

change_host_name中的以下行在设置主机名时,将虚拟机主机名和虚拟机名称作为别名添加到127.0.0.1中,这与vagrant-hostmanager的别名冲突。

sed -i'' '1i 127.0.0.1\t#{name}\t#{basename}' /etc/hosts

Vagrant的作者说这是故意的,他们不打算修复它,因为只要你不修改/etc/hosts (Vagrant -hostmanager会修改),它就可以正常工作。

有趣的是,许多工具(dig、host、nslookup)使用LAST指定的别名,这与默认的Vagrant行为配合得很好。不幸的是,其他工具,即使用gethostbyname或/etc/nsswitch.conf的工具,有不同的行为。 例如,Ping似乎在/etc/hosts中使用第一个别名,而Curl(当编译为使用NSS时)使用多个别名作为自上而下的回退。

因此,通常不鼓励使用别名匹配多个ip。

以下Vagrantfile解决方案应该是足够的:

config.hostmanager.enabled = true
name = "name"
hostname = "hostname"
config.vm.define name do |machine|
  machine.vm.hostname = hostname
  machine.vm.provision :shell, inline: "sed -i'' '/^127.0.0.1\t#{hostname}\t#{name}$/d' /etc/hosts"
  ...
end

最新更新