packagemainimport("fmt""io/ioutil""os""os/exec""path/filepath""strconv""syscall")// go run main.go run <cmd> <args>
funcmain(){switchos.Args[1]{case"run":run()case"child":child()default:panic("help")}}funcrun(){fmt.Printf("Running %v \n",os.Args[2:])cmd:=exec.Command("/proc/self/exe",append([]string{"child"},os.Args[2:]...)...)cmd.Stdin=os.Stdincmd.Stdout=os.Stdoutcmd.Stderr=os.Stderrcmd.SysProcAttr=&syscall.SysProcAttr{Cloneflags:syscall.CLONE_NEWUTS|syscall.CLONE_NEWPID|syscall.CLONE_NEWNS,Unshareflags:syscall.CLONE_NEWNS,}must(cmd.Run())}funcchild(){fmt.Printf("Running %v \n",os.Args[2:])cg()cmd:=exec.Command(os.Args[2],os.Args[3:]...)cmd.Stdin=os.Stdincmd.Stdout=os.Stdoutcmd.Stderr=os.Stderrmust(syscall.Sethostname([]byte("container")))must(syscall.Chroot("/home/liz/ubuntufs"))must(os.Chdir("/"))must(syscall.Mount("proc","proc","proc",0,""))must(syscall.Mount("thing","mytemp","tmpfs",0,""))must(cmd.Run())must(syscall.Unmount("proc",0))must(syscall.Unmount("thing",0))}funccg(){cgroups:="/sys/fs/cgroup/"pids:=filepath.Join(cgroups,"pids")os.Mkdir(filepath.Join(pids,"liz"),0755)must(ioutil.WriteFile(filepath.Join(pids,"liz/pids.max"),[]byte("20"),0700))// Removes the new cgroup in place after the container exits
must(ioutil.WriteFile(filepath.Join(pids,"liz/notify_on_release"),[]byte("1"),0700))must(ioutil.WriteFile(filepath.Join(pids,"liz/cgroup.procs"),[]byte(strconv.Itoa(os.Getpid())),0700))}funcmust(errerror){iferr!=nil{panic(err)}}
// bind mount
testBindPath:=filepath.Join(rootPath,"test")os.Mkdir(testBindPath,0755)must(syscall.Mount(fmt.Sprintf("%s/test",homePath),testBindPath,"",syscall.MS_BIND,""))
// Add cpu limitation for 0.3 core
cpu:=filepath.Join(cgroups,"cpu")os.Mkdir(filepath.Join(cpu,"liz"),0755)must(ioutil.WriteFile(filepath.Join(cpu,"liz/cpu.cfs_period_us"),[]byte("100000"),0700))must(ioutil.WriteFile(filepath.Join(cpu,"liz/cpu.cfs_quota_us"),[]byte("30000"),0700))must(ioutil.WriteFile(filepath.Join(cpu,"liz/notify_on_release"),[]byte("1"),0700))must(ioutil.WriteFile(filepath.Join(cpu,"liz/cgroup.procs"),[]byte(strconv.Itoa(os.Getpid())),0700))// Add memory limitation for 100M
mem:=filepath.Join(cgroups,"memory")os.Mkdir(filepath.Join(mem,"liz"),0755)must(ioutil.WriteFile(filepath.Join(mem,"liz/memory.limit_in_bytes"),[]byte("100M"),0700))must(ioutil.WriteFile(filepath.Join(mem,"liz/memory.swappiness"),[]byte("0"),0700))must(ioutil.WriteFile(filepath.Join(mem,"liz/notify_on_release"),[]byte("1"),0700))must(ioutil.WriteFile(filepath.Join(mem,"liz/cgroup.procs"),[]byte(strconv.Itoa(os.Getpid())),0700))
- new_root and put_old must be directories.
- new_root and put_old must not be on the same mount as the current root.
- put_old must be at or underneath new_root; that is, adding some nonnegative number of "/.." prefixes to the pathname
pointed to by put_old must yield the same directory as new_root.
- new_root must be a path to a mount point, but can't be "/". A path that is not already a mount point can be con‐
verted into one by bind mounting the path onto itself.
- The propagation type of the parent mount of new_root and the parent mount of the current root directory must not be
MS_SHARED; similarly, if put_old is an existing mount point, its propagation type must not be MS_SHARED. These re‐
strictions ensure that pivot_root() never propagates any changes to another mount namespace.
- The current root directory must be a mount point.