1

我有以下代码mnt.go

package main

import (
    "fmt"
    "log"
    "os"
    "os/exec"
    "syscall"
)

func main() {
    fmt.Println("Entering go program")

    cmd := exec.Command("/bin/bash")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Stdin = os.Stdin

    cmd.SysProcAttr = &syscall.SysProcAttr{ 
        Cloneflags: syscall.CLONE_NEWNS,
    }

    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }

    fmt.Println("Exiting go program")
}

我想运行上面的代码来生成一个 bash shell,然后运行以下命令:

./mnt
mkdir /tmp/testmount
mount -n -o size=1m -t tmpfs tmpfs /tmp/testmount
cd /tmp/testmount
touch 1.txt 2.txt 3.txt

现在,当我启动另一个 shell 并运行命令时

ls /tmp/testmount

我应该看不到文件1.txt2.txt并且3.txt. 由于临时文件系统已挂载在挂载命名空间内,因此不应从外部看到它。

但这对我来说不是这样。为什么syscall.CLONE_NEWNS没有按预期工作?我应该怎么做?

其中一条评论提到这段代码对他们来说很好。FWIW,我正在运行一个安装了 golang 并且没有其他自定义的“bento/centos-7”Vagrant 盒子。

4

1 回答 1

0

我对解决方案是正确的。但我不知道为什么。出于文档的目的,我会把这篇文章完整的。如果你会看中文,请直接阅读这篇知乎专兰的帖子。那位作者在 Linux 容器和 docker 方面非常专业。

知识关键字是:共享子树传播类型:MS_SHARED、MS_PRIVATE 和 MS_SLAVE。默认情况下,系统假定您要重用已挂载的文件系统。但如果你不想这样,你必须做一些额外的工作:

一个进程想要克隆它自己的命名空间,但仍然想要访问最近挂载的 CD。共享子树语义提供了完成上述任务的必要机制。

在命令行上,您可以mount --make-rprivate /;在代码中,您需要使用syscall.MS_PRIVATE | syscall.MS_REC来创建一个隔离的挂载。

于 2020-08-04T20:49:37.443 回答