/ etc / hosts文件引用另一个配置文件


37

如何获取该/etc/hosts文件以引用其主机列表的另一个配置文件?

范例/etc/hosts

 ## My Hosts
 127.0.0.1   localhost
 255.255.255.255 broadcasthost

 #Other Configurations
 <Link to /myPath/to/MyConfig/ConfigFile.txt>

 #Other Addresses
 3.3.3.3 MyAwesomeDomain.com
 4.4.4.4 SomeplaceIWantToGoTo.com

ConfigFile.txt

##My additional Hosts
1.1.1.1 SomeLocation.com
2.2.2.2 AnotherLocation.com

如何为/etc/hosts文件添加链接/引用,以便将ConfigFile.txt加载?

Answers:


39

你不能 的格式/etc/hosts非常简单,并且不支持包含其他文件。

您可以使用几种方法代替:

  • 设置一个(可能是仅限本地的)DNS服务器。其中一些提供了很大的灵活性,您绝对可以将主机文件分布在多个文件甚至机器上。其他(例如dnsmasq)提供的灵活性较小(但仍然足够),但易于设置。如果您要在一堆机器上包括相同的主机列表,则DNS可能是正确的答案。

  • 设置其他名称服务(NIS,LDAP等)。查看glibc NSS文档以了解受支持的内容。就个人而言,我认为您在大多数情况下都应使用DNS。

  • 使自己成为/etc/hosts.d目录或类似目录,并编写一些脚本将它们串联在一起(最琐碎的:cat /etc/hosts.d/*.conf > /etc/hosts,尽管您可能希望更好一些,例如,按当前语言环境覆盖默认排序),然后在启动时运行该脚本,或者从cron或在更新文件时手动进行。

个人而言,无论是在家还是在办公室,为了使每台设备都能解析机器名称,我运行了BIND9。但是,这确实需要花费几个小时来学习。


谢谢!我想知道为什么每次尝试都失败了。如果可能的话,它会容易得多,但是我将使用/etc/hosts.d
DogEatDog 2013年

8
@DogEatDog我建议运行本地DNS服务器。Dnsmasq的设置非常容易。在用户友好的发行版上,您可以安装该软件包,并且该软件包可以正常工作。
吉尔(Gilles)'所以

@Gilles正确无误-dnsmasq可能恰好可以在家庭网络上实现您想要的功能。它使您可以通过MAC地址为所有LAN资源分配静态IP,为其分配主机名并解决对它们的请求-同时还允许未知主机传递到上游DNS服务器。
moodboom

@moodboom&Gilles谢谢你的建议,我已经在答案中指出了。不知道我是否在2013年使用dnsmasq,但现在肯定是。
derobert

Glob扩展已排序(根据至少在Bash中LC_COLLATE),因此答案中的警告不适用。
l0b0

2

这是不可能的,因为该格式通常被深度编码到平台的libc中。然而,它可以想象的OS还添加了这项功能,使之成为非跨平台解决方案。

或者,您可以自动更新主机文件中的特定块。如果您有一个脚本可以动态输出某个项目左右的主机条目(可能会更改IP),这将特别有用。

这是一个示例:您想通过从Terraform状态创建主机terraform-inventory

相关清单输出(例如,将EC2“名称”标签映射到每个主机仅一个主机的组):

$ terraform-inventory --list | jq 'with_entries(select(.key | match("^name_")))'
{
  "name_myhost-a": [
    "10.101.118.131"
  ],
  "name_myhost-b": [
    "10.101.111.189"
  ]
}

打印更新的主机条目.sh

#!/bin/sh
exec terraform-inventory --list | \
    jq -r 'to_entries |
           map(select(.key | match("^name_"))) |
           map(.value[0] + " " + .key[5:]) |
           join("\n")'

脚本输出:

./print-updated-hosts-entries.sh
10.101.118.131 myhost-a
10.101.111.189 myhost-b

使用脚本输出命令行中更新标记的块/etc/hosts

sudo cp /etc/hosts "/etc/hosts.bak.$(date +%Y%m%d%H%M%S)" && \
    (
        sed -n '1,/^# MYMARKER BEGIN/{/^# MYMARKER BEGIN/!p;}' /etc/hosts; \
        echo "# MYMARKER BEGIN"; \
        ./print-updated-hosts-entries.sh; \
        echo "# MYMARKER END"; \
        sed -n '/^# MYMARKER END/,${/^# MYMARKER END/!p;}' /etc/hosts; \
    ) | \
    sudo tee /etc/hosts.new | \
    sed -n '/^# MYMARKER BEGIN/,/^# MYMARKER END/p' && \
        sudo mv /etc/hosts.new /etc/hosts

说明:

  • 第一行显然会创建一个备份
  • 括号中的子外壳有两个sed调用,分别打印标记开始/结束之前和之后的所有行。无论如何,我们都会插入标记,将脚本输出放在这些行之间。即使脚本失败,我们仍然必须围绕内容/etc/hosts(以及灾难性情况下的备份)。
  • sudo tee /etc/hosts.new 将管道内容写入新文件
  • sed -n '/^# MYMARKER BEGIN/,/^# MYMARKER END/p' 为方便起见,打印更新的块
  • sudo mv /etc/hosts.new /etc/hosts将新文件移动到位。这必须在单独的步骤中完成,因为如果管道缓冲区空间不足,tee /etc/hosts则会在仍在读取现有内容的同时开始写入文件。

1

我对使用动态IP从不同位置无缝工作也有类似的要求,尤其是因为我使用虚拟机。我对此的简单解决方案如下:

  1. 创建一个脚本来更新每个实体的主机条目。例如,如果我有一个名为“ myhost.net”的主机,并且其子域为“ app.myhost.net”,则我将调用该脚本并提供一个将为每个域写入的IP地址,并将其保存在名为“ “我的主人”。同一脚本具有用于删除或更新单个主机文件的标志。

  2. 创建另一个脚本以将这些文件合并到/ etc / hosts中。该脚本将找到您创建的所有主机文件,并将它们合并到/ etc / hosts中的单个主机文件中。

这对我来说非常有效。我是远程工作的,有时出于任何原因或其他原因需要在位置之间移动,并且由于多次编辑该文件的需求而感到负担。相反,我只运行一个脚本。是的,一个脚本。第一个脚本自动运行,另一个脚本自动执行合并。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.