如何使符号链接的/ etc / hostname在引导时生效

时间:2016-12-22 21:17:01

标签: linux symlink hostname

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

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

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

的信息:

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

systemd在启动时管理服务。

当前/ etc / hosts

127.0.0.1       ABC123.localdomain              ABC123

当前/ etc / hostname

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 restart systemd-networkd.service

2 个答案:

答案 0 :(得分:0)

您必须在hostname命令之后重新启动网络服务。

systemctl restart systemd-networkd.service

– schustercp

答案 1 :(得分:0)

我正在寻找类似的功能。

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

但是,在更深入地挖掘之后,事情就变得不那么简单了。从我在其他地方找到的:

我希望initramfs将您的/ etc / hostname与实际的主机名打包在一起,也许您需要重新生成initramfs?

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

因此,我最终得到了Daniel Schepler提供的解决方案。 这是系统服务:

[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,这一点很重要,因为它的依赖项尚未加载,它将失败!

该解决方案无需启动网络服务即可工作,因为它尚未启动。它也仅需重启一次即可。