【问题标题】:unshare command doesn't create new PID namespaceunshare 命令不会创建新的 PID 命名空间
【发布时间】:2021-08-08 21:11:49
【问题描述】:

我正在学习 linux 核心,我现在正在讨论 namepsaces 主题。 我尝试使用“unshare”命令只是为了了解命名空间及其要点。 问题是它没有,或者更有可能的是,我做错了什么。 如果您能帮助我理解,我将不胜感激。 我尝试在它自己的 PID 命名空间中执行busybox sh 程序。我就是这样做的:

[ab@a ~]$ sudo unshare --pid  busybox sh
/home/ab # ps
PID TTY          TIME CMD
6014 pts/1    00:00:00 sudo
6016 pts/1    00:00:00 busybox
6026 pts/1    00:00:00 ps

所以我可以从 ps 命令的输出中看到,所有进程在新环境中都是可见的。当我检查新创建的进程和当前进程的 pid 命名空间 id 时,它得到确认。见下文

[ab@a ~]$ ps -p 6016,$$
PID TTY          TIME CMD
4604 pts/0    00:00:00 bash
6016 pts/1    00:00:00 busybox
[ab@a ~]$ sudo ls -l /proc/4604/ns
total 0
lrwxrwxrwx. 1 ab ab 0 Aug  8 23:49 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 ab ab 0 Aug  8 23:49 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 ab ab 0 Aug  8 23:49 net -> net:[4026531968]
lrwxrwxrwx. 1 ab ab 0 Aug  8 23:49 pid -> pid:[4026531836]
lrwxrwxrwx. 1 ab ab 0 Aug  8 23:49 user -> user:[4026531837]
lrwxrwxrwx. 1 ab ab 0 Aug  8 23:49 uts -> uts:[4026531838]
[ab@a ~]$ sudo ls -l /proc/6016/ns
total 0
lrwxrwxrwx. 1 root root 0 Aug  9 00:07 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0 Aug  9 00:07 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Aug  9 00:07 net -> net:[4026531968]
lrwxrwxrwx. 1 root root 0 Aug  9 00:07 pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0 Aug  9 00:07 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Aug  9 00:07 uts -> uts:[4026531838]

因此,尽管我为 unshare 调用提供了 --pid 参数,但 pid 命名空间保持不变。 你能帮我理解为什么会这样吗? 谢谢

【问题讨论】:

    标签: namespaces linux-namespaces


    【解决方案1】:

    解决方案

    您应该按照手册页中的说明将--fork--mount-proc 切换到unshare

    -f, --fork
              Fork the specified program as a child process of unshare rather than running it directly. This is useful
              when creating a new PID namespace. Note that when unshare is waiting for the child process, then it
              ignores SIGINT and SIGTERM and does not forward any signals to the child. It is necessary to send
              signals to the child process.
    

    解释(来自man pid_namespaces

    进程的 PID 命名空间成员资格在进程创建时确定,此后无法更改。

    当您提供 --pid 时,unshare 的实际作用是将当前进程的文件描述符设置为 /proc/[PID]/ns/pid_for_children 到新的 PID 命名空间,从而导致随后由该进程创建的子进程被放置在不同的 PID 命名空间中( 它的孩子不是它自己!!重要!)。

    因此,当您将 --fork 提供给 unshare 时,它会将您的程序(在本例中为 busybox sh)作为 unshare 的子进程分叉,并将其放置在新的 PID 命名空间中。

    为什么我需要--mount-proc

    尝试仅使用 --pid--fork 运行 unshare,看看会发生什么。

    wendel@gentoo-grill ~ λ sudo unshare --pid --fork busybox sh
    /home/wendel # echo $$
    1
    /home/wendel # ps
    PID   USER     TIME  COMMAND
    12443 root      0:00 unshare --pid --fork busybox sh
    12444 root      0:00 busybox sh
    24370 root      0:00 {ps} busybox sh
    .
    .
    . // bunch more
    

    echo $$我们可以看到pid实际上是1,所以我们知道我们必须在新的PID命名空间中,但是当我们运行ps时,我们看到其他进程就好像我们仍然在父PID命名空间中一样.

    这是因为 /proc 是一个名为 procfs 的特殊文件系统,该文件系统是内核在内存中创建的,并且来自手册页。

    /proc 文件系统仅显示(在/proc/[pid] 目录中)在执行挂载的进程的 PID 命名空间中可见的进程,即使从其他命名空间中的进程查看 /proc 文件系统也是如此。

    因此,为了使ps 等工具正常工作,我们需要使用新命名空间中的进程重新挂载/proc

    但是,假设您的进程位于根挂载命名空间中,如果我们重新挂载/proc,这将对同一挂载命名空间中的其他进程造成很多麻烦,因为现在它们什么都看不到(在/proc)。所以你也应该把你的进程也放在新的挂载命名空间中。

    好消息是取消分享 --mount-proc

    --mount-proc[=mountpoint]
              Just before running the program, mount the proc filesystem at mountpoint (default is /proc). This is useful when creating a new PID namespace. It also implies creating a new mount namespace since the /proc mount would
              otherwise mess up existing programs on the system. The new proc filesystem is explicitly mounted as private (with MS_PRIVATE|MS_REC).
    

    让我们验证--mount-proc 是否也将您的进程放入新的挂载命名空间中。

    在外面猛烈抨击:

    wendel@gentoo-grill ~ λ ls -go /proc/$$/ns/{user,mnt,pid}
    lrwxrwxrwx 1 0 Aug  9 10:05 /proc/17011/ns/mnt -> 'mnt:[4026531840]'
    lrwxrwxrwx 1 0 Aug  9 10:10 /proc/17011/ns/pid -> 'pid:[4026531836]'
    lrwxrwxrwx 1 0 Aug  9 10:10 /proc/17011/ns/user -> 'user:[4026531837]'
    

    忙箱:

    wendel@gentoo-grill ~ λ doas ls -go /proc/16436/ns/{user,mnt,pid}
    lrwxrwxrwx 1 0 Aug  9 10:05 /proc/16436/ns/mnt -> 'mnt:[4026533479]'
    lrwxrwxrwx 1 0 Aug  9 10:04 /proc/16436/ns/pid -> 'pid:[4026533481]'
    lrwxrwxrwx 1 0 Aug  9 10:17 /proc/16436/ns/user -> 'user:[4026531837]'
    

    请注意,他们的用户命名空间是相同的,但 mount 和 pid 不同。

    注意:您可以看到我从手册页中引用了很多内容。如果您想了解更多关于 linux 命名空间(或任何真正的 unix)的信息,您首先要做的是阅读每个命名空间的手册页。它写得很好,内容丰富。

    【讨论】:

    • 非常感谢您的及时回复!这真的很有帮助。你能否再为我澄清一件事。为什么我可以从busybox外面的bash中看到busybox仍然在同一个pid命名空间中,而从busybox执行 ls -l /proc/$$/ns 会给出不同的pid命名空间ID?这是否意味着我无法从主机看到容器的 pid 命名空间 id?
    • @AndrewBolotov 对不起,我不太明白你的问题。你能改写你的问题吗?
    • 谢谢,看来我在检查 PID 命名空间 ID 时提供了错误的 PID,这是造成混乱的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 2016-07-15
    • 2021-01-19
    相关资源
    最近更新 更多