為什麼 UTS 命名空間隔離不起作用?
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
)。
hostnamectl
隨systemd環境而來,它不執行sethostname(2)
系統呼叫。它通過套接字要求systemd執行此操作。/run/dbus/system_bus_socket
由於systemd沒有更改命名空間,它在初始命名空間中執行此操作,將舊 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
如果一個人阻止上面的呼叫成功(通過使用然後用 a
unshare -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
在這種環境中,應該使用用於讀取或更改主機名的低級“遺留”命令。它確實直接呼叫sethostname(2)
系統呼叫:它將更改新的 UTS 命名空間的名稱並保持舊的(初始)UTS 命名空間不變:hostname newhostname
為了
hostnamectl
影響新的 UTS 命名空間(就像使用 LXC 啟動的完整容器),這需要的不僅僅是一個unshare
命令:一個全新的systemd生態系統實例必須存在於新環境中,可能需要幾個其他命名空間輸入/取消共享和許多額外的樣板。