实验 / 查资源视图的身份
实测边界
比较 namespace 身份,比比较主机名或进程名更可靠。/proc/<pid>/ns/ 中的符号链接指向进程所属 namespace。readlink 读取链接目标;同一 Linux 内核中,同一类型的目标相同,表示处于同一个 namespace。数字是内核分配的身份编号,不是容器 ID。[1]
适用条件:下面的宿主对照须在运行 Docker Engine 的原生 Linux 主机上执行,使用普通 rootful、未启用 remap 的配置。需要可访问 Docker,并可用 sudo 读取进程信息。Docker Desktop 的容器位于 Linux 虚拟机内;远程 context 的 PID 属于远端,不能拿本机的 /proc 去查。Rootless 的内外视图也不同。[12]
① 在宿主的同一个 shell 启动一个临时容器。它最多运行 600 秒;记下变量,后续命令接着执行。inspect 的 .State.Pid 给出主进程在该 Engine 宿主中的 PID。[13]
ns_cid=$(docker run --rm -d --network none --ipc private --hostname ns-lab alpine:3.21 sleep 600)
ns_pid=$(docker inspect --format '{{.State.Pid}}' "$ns_cid")
printf 'container=%s host-pid=%s\n' "$ns_cid" "$ns_pid"
② 比较宿主 shell 与容器主进程。/proc/$$ 指宿主 shell;不使用 /proc/1 代替你的 shell,以免把不同运行环境混在一起。
for ns_kind in pid net mnt uts ipc user; do
printf '\n%s\n' "$ns_kind"
readlink "/proc/$$/ns/$ns_kind"
sudo readlink "/proc/$ns_pid/ns/$ns_kind"
done
预期:在上述配置下,pid、net、mnt、uts、ipc 两行目标不同;user 通常相同。若不符合,先查运行模式、共享参数和命令所在的主机,不要把某组固定编号当标准答案。
③ 从容器里读同一进程的 PID namespace。接着在宿主用 util-linux 提供的 lsns 汇总容器主进程的 namespace,显式指定输出列。[14]
docker exec "$ns_cid" readlink /proc/1/ns/pid
sudo readlink "/proc/$ns_pid/ns/pid"
sudo lsns --list --task "$ns_pid" --output NS,TYPE,NPROCS,PID,COMMAND
预期:前两条命令的链接目标相同,因为它们指向同一个主进程的 PID namespace;两次使用的进程编号却不同。lsns 的 NS 是身份编号,TYPE 是类型,NPROCS 是当前可见的成员数,PID/COMMAND 描述代表进程,不是每种 namespace 各运行一个进程。
④ 观察完即清理。只删除本次变量记录的实验容器;若已经超时退出,--rm 已完成清理。
为什么宿主用 /proc/$ns_pid、容器用 /proc/1,却能读到相同的 PID namespace 身份?用两句话解释。
两条路径按各自视图选择同一个容器主进程。进程编号随观察视图改变,但该进程所属的 PID namespace 没有改变。
- 区分了进程编号与 namespace 身份。
- 说明了同一进程仍在同一个内核中运行。
没有原生 Linux 宿主,或查询失败怎么办?
Docker Desktop 可先做前面的六个容器内探针,以及 docker exec 的读取;宿主对照实验请换到 Linux Engine 主机,不用特权容器去绕过边界。
查不到进程时,先确认容器仍在运行、ns_pid 不是 0,且 CLI 没连远端。权限不足时,在 Engine 宿主使用允许的管理员权限。lsns 只能列当前可访问的信息;不是整台物理机的全知视图。
你可能还看到 cgroup、time、pid_for_children 等条目。Linux 的 namespace 不止本页六种;cgroup namespace 是控制组路径视图,资源额度则由 cgroups(控制组)机制控制,下一页再学。