CentOS 8 Docker 容器中的 who 和 w 命令

who and w commands in CentOS 8 Docker container

我在 Docker 容器上使用 CentOs 8 时发现,whow 命令的输出总是空的。

[root@9e24376316f1 ~]# who
[root@9e24376316f1 ~]# w
 01:01:50 up  7:38,  0 users,  load average: 0.00, 0.04, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT

即使我在第二个终端中以不同的用户身份登录。 当我想 write 给这个用户时,它显示

[root@9e24376316f1 ~]# write test
write: test is not logged in

这是因为Docker吗?也许它以某种方式起作用,不允许会话互相看到? 或者这可能是其他问题。我真的很感激一些解释。

这些实用程序从 utmp 文件 (/var/run/utmp) 中获取有关当前登录的信息。您可以轻松检查在普通情况下(例如在桌面系统上)此文件是否包含类似以下字符串的内容(这里 qazer 是我的登录名,tty7 是我的桌面环境运行的 TTY):

$ cat /var/run/utmp
tty7:0qazer:0�o^�

而在容器中这个文件是(通常)空的:

$ docker run -it centos
[root@5e91e9e1a28e /]# cat /var/run/utmp
[root@5e91e9e1a28e /]#

为什么?

utmp 文件通常由验证用户身份并启动会话的程序修改:login(1)sshd(8)lightdm(1)。但是容器引擎不能依赖它们,因为它们在容器文件系统中可能不存在,所以"logging in"和"executing on behalf of"以最原始和直接的方式实现,避免依赖容器内的任何东西

当任何容器启动或任何命令在其中 execd 时,容器引擎 只是 生成新进程,安排一些安全设置,调用 setgid(2)/setuid(2) 强制(无需任何身份验证)更改进程' UID/GID 然后在此进程中执行所需的二进制文件(入口点、命令等)。

说,我启动 CentOS 容器 运行 它代表 UID 的主进程 42:

docker run -it --user 42 centos

然后尝试在里面执行sleep 1000:

docker exec -it $CONTAINER_ID sleep 1000

容器引擎将执行如下操作:

[pid 10170] setgid(0)                   = 0
[pid 10170] setuid(42)                  = 0
...
[pid 10170] execve("/usr/bin/sleep", ["sleep", "1000"], 0xc000159740 /* 4 vars */) = 0

将不会写入 /var/run/utmp,因此它将保持为空,并且 who(1)/w(1) 不会在容器内找到任何登录。