【问题标题】:How do I get a symlinked /etc/hostname to take effect at boot如何让符号链接的 /etc/hostname 在启动时生效
【发布时间】:2016-12-22 21:17:00
【问题描述】:

我正在开发具有 3 个不同 Linux 分区的嵌入式 Linux 设备。最终用途选择从哪个分区启动。根文件系统是只读的。有第四个分区以读写方式安装。我需要 Linux 的所有实例来抵抗与 DNS 服务器相同的名称(即使用相同的主机名)。由于每个设备都需要一个唯一的主机名,因此在创建文件系统时主机名是未知的,稍后会分配主机名。我所做的是在读写分区上创建一个文件,该文件将在以后被覆盖。然后我将 /etc/hostname 更改为该文件的符号链接。我知道在安装读写分区之前无法读取该文件,我相信这是我的问题。如果我将 /etc/hostname 设置为普通文件,那么该文件中指定的任何内容都可以正常工作。更改 /etc/hosts 似乎没有任何作用。

想要的结果是控制 WiFi 连接时向 DNS 服务器注册的名称。我发现控制它的唯一方法是通过主机名。 /etc/hosts 文件似乎没有影响它。如果主机名文件不可读或未设置,则 Linux 将其默认为“localhost”,并且不会向 DNS 注册任何有用的内容。

WiFi 由启动后运行的应用程序通过 rfkill 启用。在启用 WiFi 之前在脚本中运行某些内容是一种可能的解决方案。在启用 WiFi 之前,我无法通过在命令行上更改主机名来成功更改向 DNS 注册的内容。我可以更改主机名,但在 DNS 中注册的内容不会更改。

信息:

Linux 内核是 3.14.60,是基于 yocto 的构建。

systemd 在启动时管理服务。

当前的 /etc/hosts

127.0.0.1       ABC123.localdomain              ABC123

当前 /etc/主机名

SerialNumberGoesHere

以下是启动后查看主机名的所有方法:

>hostname
localhost

>hostnamectl status
   Static hostname: SerialNumberGoesHere
Transient hostname: localhost
         Icon name: computer
        Machine ID: 4cdac8e5dce348d2bfc133dd393f6172
           Boot ID: 9b8c9da934e748fc86606c4a24f57f9e
  Operating System: Linux
            Kernel: Linux 3.14.60+g02d9429
      Architecture: arm

>uname -n
localhost

>echo /proc/sys/kernel/hostname
localhost

>sysctl kernel.hostname
kernel.hostname = localhost

如您所见,“hostnamectl status”选择了正确的静态主机名,但内核没有。

在设备上

>nslookup 192.168.12.238
Server:    192.168.12.6
Address 1: 192.168.12.6 dc1.hq.com

Name:      192.168.12.238
Address 1: 192.168.12.238 linux.local

在另一台计算机上(Ping 192.168.12.238 有效)

>nslookup 192.168.12.238
Server:     127.0.1.1
Address:    127.0.1.1#53

** server can't find 238.12.168.192.in-addr.arpa: NXDOMAIN

如果我将主机名符号链接更改为真实文件,这是期望的结果:

>hostname
SerialNumberGoesHere

>hostnamectl status
   Static hostname: SerialNumberGoesHere
         Icon name: computer
        Machine ID: 4cdac8e5dce348d2bfc133dd393f6172
           Boot ID: ed760b42b7ae414881bc2d9352a8bb82
  Operating System: ARANZ Sugar-Free Silhouette Star M2 (fido)
            Kernel: Linux 3.14.60+g02d9429
      Architecture: arm

>uname -n
SerialNumberGoesHere

>echo /proc/sys/kernel/hostname
SerialNumberGoesHere

>sysctl kernel.hostname
kernel.hostname = SerialNumberGoesHere

在设备上

> nslookup 192.168.12.238
Server:    192.168.12.7
Address 1: 192.168.12.7 dc1.hq.com

Name:      192.168.12.238
Address 1: 192.168.12.238 serialnumbergoeshere.hq.com

在另一台计算机上

> nslookup 192.168.12.238
Server:     127.0.1.1
Address:    127.0.1.1#53

238.12.168.192.in-addr.arpa name = serialnumbergoeshere.hq.com.

2017 年 1 月 10 日更新

我找到了答案。您必须在执行 hostname 命令后重新启动网络服务。

systemctl 重启 systemd-networkd.service

【问题讨论】:

  • 在挂载 r/w 分区后和初始化 wifi 之前重新读取主机名 (hostname -F /path/to/file iirc) 以及任何其他服务会注意主机名
  • 您能否创建一个自定义 systemd 单元,该单元设置为在挂载文件系统之后但在 systemd-networkd.service 之前运行?

标签: linux symlink hostname


【解决方案1】:

我一直在寻找类似的功能。

我的第一个想法也是将 /etc/hostname 符号链接到另一个分区上的文件,并确保在出现以下引导消息之前挂载该分区:systemd[1]: Set hostname to <myhostname>

但是,在深入挖掘之后,事情并没有那么简单。根据我在其他地方找到的:

我原以为 initramfs 会将您的 /etc/hostname 与实际主机名打包,也许您需要重新生成 initramfs?

systemd 在 initramfs 的早期启动,它从 initramfs 设置主机名,但在将 root 切换到实际系统后,它会重新执行并再次设置主机名,因此无论如何你应该以正确的主机名结束

所以我最终选择了 Daniel Schepler 提供的解决方案。 这里是 systemd 服务:

[Unit]
Description=Update hostname to what we want
Before=systemd-networkd.target
After=mountdata.service
RequiresMountsFor=/usr
DefaultDependencies=no

[Service]
Type=simple
ExecStart=/usr/bin/mycustomhostnamescript.sh

[Install]
WantedBy=multi-user.target

脚本:

...
    hostn=$(cat "$FILE_SERIAL")
    echo "setting hostname=$hostn"
    echo "$hostn" > /etc/hostname
    hostname "$hostn"
...

请务必不要在脚本中使用 hostnamectl,因为它的依赖项尚未加载,它会失败!

该解决方案无需重新启动网络服务即可运行,因为它尚未启动。它也适用于仅重新启动一次。

【讨论】:

  • 我喜欢这个解决方案。问题,您的 $FILE_SERIAL 环境变量设置在哪里?您能否进一步解释“它也适用于仅重新启动一次”。如果系统是使用安装的脚本构建的,那么您不必重新启动。我知道如果您的 $FILE_SERIAL 发生更改,您将不得不重新启动。
  • 关于$FILE_SERIAL:它是mycustomhostnamescript.sh 中静态定义的变量,例如它可以指向/mnt/datapart/serialnumber。关于“它也适用于仅重新启动一次”。我的意思是,当您安装此系统服务和脚本时,您只需重新启动一次即可生效。这是我必须满足的要求,也许在这里提及并不那么重要:) 但是例如,您也可以在网络服务启动后启动 systemd 服务。在这种情况下,需要再次重新启动。希望澄清事情
  • 完美运行,感谢杰弗里。作为OP,我在由mender管理的嵌入式设备上使用它来进行系统更新。因此所有设备共享相同的 rootfs,个性化在单独的分区上。所以 /etc/hostname 是 /data/etc/hostname 的符号链接。使用此 systemd 服务,它可以完美运行。就我而言,我可以稍微简化一下,因为它是一个符号链接并使用ExecStart=hostname -F /etc/hostname,它工作正常。
【解决方案2】:

您必须在执行主机名命令后重新启动网络服务。

systemctl restart systemd-networkd.service

--schustercp

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    相关资源
    最近更新 更多