1. 在单独的子UTS命名空间下启动shell进程
sudo unshare -f --mount-proc -u /bin/bash
2.在此过程中更改主机名
hostnamectl set-hostname newhostname
3.从不同的shell监视变化
$ hostname
newhostname
预期结果
该进程在父命名空间中保留其旧主机名。
结果得到
更改新 UTS 命名空间中的主机名也会更改父命名空间中的主机名。
为什么会发生这种情况?我使用的是 Ubuntu 20.04,内核版本 5.10.23-xanmod1 ( uname -r
)。
答案1
hostnamectl
随之而来的是系统环境并且它不执行sethostname(2)
系统调用。它问系统通过套接字来做到这一点/run/dbus/system_bus_socket
。作为系统没有更改命名空间,它在初始命名空间中执行此操作,将旧UTS命名空间的名称(运行时的初始名称)更改为提供的新名称,并保留新UTS命名空间的名称不变(与OP的声明相反) :旧主机名。还会有其他副作用,例如文件/etc/hostname
被更改。
这可以使用 检查strace
。里面没有sethostname(2)
,但是有可见的 systemd 相关元素:
newfstatat(AT_FDCWD, "/run/systemd/system/", {st_mode=S_IFDIR|0755, st_size=40, ...}, AT_SYMLINK_NOFOLLOW) = 0
如果阻止上面的调用成功(通过使用然后用 aunshare -f -u -m /bin/bash
将其全部覆盖),则会得到:/run
mount -t tmpfs tmpfs /run
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
该对话框稍后通过打开的套接字完成,如下所示:
connect(3, {sa_family=AF_UNIX, sun_path="/run/dbus/system_bus_socket"}, 30) = 0
hostname
在这种环境中,应该使用用于读取的低级“legacy”命令或者更改主机名。它确实直接调用sethostname(2)
系统调用:它将更改新的 UTS 命名空间的名称,并保持旧的(初始)UTS 命名空间不变:
hostname newhostname
为了hostnamectl
影响新的 UTS 命名空间(就像使用 LXC 启动的完整容器一样),这需要的不仅仅是一个unshare
命令:一个全新的 UTS 实例系统生态系统必须存在于新环境中,可能需要输入/取消共享几个其他名称空间以及许多额外的样板文件。