3

在 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 吗?也许它以某种方式工作,不允许会话互相看到?或者这可能是其他问题。我真的很感激一些解释。

4

1 回答 1

2

这些实用程序从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). 但是容器引擎不能依赖它们,因为它们在容器文件系统中可能不存在,所以“登录”和“代执行”以最原始、最直接的方式实现,避免依赖容器内部的任何东西.

当任何容器启动或在其中执行任何命令exec时,容器引擎只是生成新进程,安排一些安全设置,调用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)不会在容器内找到任何登录。

于 2020-03-16T22:31:52.267 回答