为什么top命令下会有user为数字的用户?

为什么top命令下会有user为数字的用户?

平时做应急的过程中,排查过程使中用htop或者top经常会发现很多user是数字的用户,但是去看/etc/passwd却没有对应的用户?并且进程/proc目录对应的目录和可执行文件都在不存在。本文通过实践解决了自己在工作中的对于一些技术细节上的疑惑。

以上面的user为33为例,所对应的pid为19390。

并且路径和文件都不存在,说明文件并不在宿主机上。

我们换成htop命令查看。发现进程链中这个apache2的父进程是containerd-shim-runc-v2,也就说明apache2是容器中的进程。

既然是容器中的文件那么宿主机无法打开也就可以解释了。

思考1:所以这里对应的user对应的数字33也就是容器中的用户?

进到容器中查看进程信息。

对应/etc/passwd的www-data用户的uid号。

就能说明为什么宿主机的命令下执行top命令看到的进程user为数字了。

思考2:为什么容器内的www-data不能在宿主机上显示,而是对应的uid呢?

我的猜测是这个uid其实是一个映射。为了证实我的想法。

以games用户为例对/etc/passwd修改,将其uid从12改为33测试。

再次htop命令查看。

发现原本的33变为了games。

也就是说从容器中进程的user的uid是通过查找主机上的/etc/passwd来展示的。本来宿主机上是没有uid为33的用户,所以就显示当前的容器内user的uid了(数字显示)。而我将uid改过之后就以对应的用户名显示了。

所以很有可能在宿主机上通过top等命令看到的进程所属用户是不正确的!

同理图中由容器fork出来的apache2 -DFOREGROUND对应的user为root的用户也不是宿主机上的root用户,只是在容器内刚好uid为0,映射到宿主机上也为0即root用户。

所以虽然 apache2 -DFOREGROUND 和上面 containerd-shim-runc-v2 显示的user同为root,但是两者的意义完全不同。

思考3:宿主机的top和容器内的top哪里不一样?

我在容器内也安装了htop命令,cpu内存这里和宿主机的信息都是一致的,唯独不同的是进程信息。

/proc是个伪文件系统,存在于内存之中而不是硬盘上。通过它可以和内核内部数据结构进行交互,获取 有关进程的有用信息。
/proc中会有以下文件:

  • /proc/cpuinfo – CPU 的信息(型号, 家族, 缓存大小等)
  • /proc/meminfo – 物理内存、交换空间等的信息
  • /proc/mounts – 已加载的文件系统的列表
  • /proc/devices – 可用设备的列表
  • /proc/filesystems – 被支持的文件系统
  • /proc/modules – 已加载的模块
  • /proc/version – 内核版本
  • /proc/cmdline – 系统启动时输入的内核命令行参数
  • /proc/{pid} – 进程信息

top正是通过/proc来获取当前内存、CPU信息的。dock er启动的容器共享操作系统内核,在容器启动的时候会挂载部分/proc里面的文件,能否通过top在docker中看到内存和CPU信息,主要看有没有挂载这些文件。

那么需要手动挂载这些文件吗?一般来说不需要,挂载内容的多少一般和镜像有关。一般的redhat/ubuntu镜像都是会挂载内存CPU信息的,精简的dokcer镜像信息会少些,有时top得到的信息不全面。

经过上面分析top看到信息的多少取决于/proc里面内容,由于pid 命名空间的隔离,宿主机的pid信息不会被启动容器挂载,所以看不到容器外宿主机进程。

延伸思考4:那么能在容器中监控宿主机的进程吗?

在docker中,可以透过”–pid”参数来将host的pid namespace带入到container中,这样就可以在docker instance中直接看到host的process了。

以busybox为例正常启动容器/proc目录下只有容器内的进程信息。

在启动容器时带上–pid=host 参数就会把宿主机上的/proc目录挂载到容器中,此时就能在容器中监控到所有宿主机上的进程信息了。

总结:
虽然这个问题本身在技术上无关紧要,也就是top对于容器内进程的用户uid在宿主机上通过/etc/passwd造成了错误的映射关系。我感觉这里更多是问题思考和探索能力的一种提升。

Print Friendly, PDF & Email
赞赏

微信赞赏支付宝赞赏

Zgao

愿有一日,安全圈的师傅们都能用上Zgao写的工具。